wxPython ScrolledWindow滚动后新绘制内容无法渲染问题求助
问题根因
- 拖动绘制时的逻辑同时绑定了
ClientDC和内存位图进行同步绘制,滚动后的DC坐标偏移和内存位图的绝对坐标映射逻辑冲突,新绘制的线条虽然写入了内存位图,但没有正确刷新到当前可见窗口区域 - 绘制完成后没有主动触发窗口重绘,系统仅在窗口区域被遮挡、滚动切换等场景才会触发
EVT_PAINT事件拉取内存位图的最新内容渲染,因此滚动切换区域后才能看到新绘制的线条
修复方案
只需要调整绘制逻辑:所有绘制操作仅针对内存位图执行,绘制完成后主动触发重绘,由统一的EVT_PAINT回调负责处理滚动偏移、把内存位图内容渲染到当前可视区域即可。
修复后的完整代码如下:
import wx class MainFrame(wx.Frame): def __init__(self, *args, **kw): wx.Frame.__init__(self, *args, **kw) s = wx.BoxSizer(wx.VERTICAL) panel = DrawablePanel(self) s.Add(panel, 1, wx.EXPAND) self.SetSizer(s) self.SetSize(400, 400) class DrawablePanel(wx.ScrolledWindow): def __init__(self, parent): super().__init__(parent, id=wx.ID_ANY) self.SetScrollbars(10, 10, 100, 100) self.buffer = wx.Bitmap((1000, 1000)) # 初始化内存位图清空为白色 dc = wx.MemoryDC(self.buffer) dc.Clear() dc.SelectObject(wx.NullBitmap) self.mouse_pos = None self.Bind(wx.EVT_PAINT, self.on_paint) self.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) self.Bind(wx.EVT_MOTION, self.on_motion) def on_paint(self, evt): wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA) def on_mouse_down(self, evt): self.mouse_pos = self.CalcUnscrolledPosition(evt.GetPosition()).Get() def on_motion(self, evt): if evt.Dragging() and evt.LeftIsDown(): new_pos = self.CalcUnscrolledPosition(evt.GetPosition()).Get() # 直接用MemoryDC操作内存位图 dc = wx.MemoryDC(self.buffer) dc.DrawLine(*self.mouse_pos, *new_pos) dc.SelectObject(wx.NullBitmap) # 主动触发重绘刷新当前视图 self.Refresh() self.mouse_pos = new_pos if __name__ == "__main__": app = wx.App() wx.InitAllImageHandlers() MainFrame(None).Show() app.MainLoop()
内容的提问来源于stack exchange,提问作者jeremy trips
相关产品推荐
相关产品推荐

