wxPython实现可点击穿透透明图片窗口,无法加载图片及调整大小如何解决
修复实现方案
核心问题说明
- 原代码硬编码加载系统桌面壁纸作为显示内容,没有用到用户输入的自定义图片
- 开启了
WS_EX_TRANSPARENT扩展属性后鼠标事件会直接穿透窗口,导致无法拖拽移动、调整窗口大小 - 没有绑定窗口尺寸变化事件,窗口缩放时图片无法同步适配
- 存在冗余的图片转存步骤,无需将图片存为本地bmp文件后再读取,可直接从PIL对象转成wx位图
可直接运行的修正代码
from win32api import GetSystemMetrics import win32con import win32gui from PIL import Image import wx # 全局变量:标记是否允许操作窗口(临时关闭穿透) allow_operate = False def scale_bitmap(bitmap, width, height): image = wx.ImageFromBitmap(bitmap) image = image.Scale(width, height, wx.IMAGE_QUALITY_HIGH) result = wx.BitmapFromImage(image) return result # 加载用户指定的自定义图片 image_path = "C:\\Users\\Daniel\\Desktop\\Tracing Images\\" imageName = input("请输入图片文件名:") im1 = Image.open(image_path + imageName) # 直接转wx位图,无需本地存文件 im1 = im1.convert("RGBA") width, height = im1.size wx_image = wx.Image(width, height) wx_image.SetData(im1.convert("RGB").tobytes()) if im1.mode == "RGBA": wx_image.SetAlpha(im1.getchannel("A").tobytes()) bmp1 = wx_image.ConvertToBitmap() app = wx.App() trans = 50 # 窗口增加标题栏方便拖动,保留 resize 和置顶属性 frame1 = wx.Frame(None, -1, "KExA", size=(width, height), style=wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP) # 图片控件 bitmap1 = wx.StaticBitmap(frame1, -1, bmp1, (0, 0)) frame1.Show() hwnd = frame1.GetHandle() # 初始开启点击穿透 extendedStyleSettings = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, extendedStyleSettings | win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT) win32gui.SetLayeredWindowAttributes(hwnd, 0, trans, win32con.LWA_ALPHA) frame1.SetTransparent(trans) # 键盘事件:上下键调透明度,Alt键切换操作/穿透状态 def onKeyDown(e): global trans, allow_operate key = e.GetKeyCode() # 上下键调整透明度 if key == wx.WXK_UP: trans = min(trans + 10, 255) elif key == wx.WXK_DOWN: trans = max(trans - 10, 0) # Alt键切换是否允许操作窗口 elif key == wx.WXK_ALT: allow_operate = not allow_operate ex_style = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) if allow_operate: # 关闭穿透,允许操作 win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, ex_style & ~win32con.WS_EX_TRANSPARENT) else: # 开启穿透 win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, ex_style | win32con.WS_EX_TRANSPARENT) try: win32gui.SetLayeredWindowAttributes(hwnd, 0, trans, win32con.LWA_ALPHA) except: pass e.Skip() # 窗口大小变化事件:同步缩放图片 def on_size(e): new_width, new_height = frame1.GetClientSize() if new_width <=0 or new_height <=0: return scaled_bmp = scale_bitmap(bmp1, new_width, new_height) bitmap1.SetBitmap(scaled_bmp) e.Skip() frame1.Bind(wx.EVT_KEY_DOWN, onKeyDown) frame1.Bind(wx.EVT_SIZE, on_size) app.MainLoop()
使用说明
- 启动后输入指定目录下的图片文件名即可加载自定义图片
- 按Alt键即可切换点击穿透状态,关闭穿透时可以正常拖拽窗口、拖动边框调整大小,开启穿透后鼠标事件可正常穿透到下层窗口
- 上下方向键调整窗口透明度,每次调整步长为10,透明度范围0-255
- 窗口缩放时内部图片会自动适配窗口大小
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

