为什么我的缓冲GraphicsContext应用会出现闪烁问题?

1 投票
2 回答
1042 浏览
提问于 2025-04-15 20:28
import wx

class MainFrame(wx.Frame):
    def __init__(self,parent,title):

        wx.Frame.__init__(self, parent, title=title, size=(640,480))
        self.mainPanel=DoubleBufferTest(self,-1)

        self.Show(True)

class DoubleBufferTest(wx.Panel):
    def __init__(self,parent=None,id=-1):
        wx.Panel.__init__(self,parent,id,style=wx.FULL_REPAINT_ON_RESIZE)

        self.SetBackgroundColour("#FFFFFF")

        self.timer = wx.Timer(self)
        self.timer.Start(100)        
        self.Bind(wx.EVT_TIMER, self.update, self.timer)
        self.Bind(wx.EVT_PAINT,self.onPaint)


    def onPaint(self,event):
        event.Skip()
        dc = wx.MemoryDC()
        dc.SelectObject(wx.EmptyBitmap(640, 480))
        gc = wx.GraphicsContext.Create(dc)
        gc.PushState()
        gc.SetBrush(wx.Brush("#CFCFCF"))
        bgRect=gc.CreatePath()
        bgRect.AddRectangle(0,0,640,480)
        gc.FillPath(bgRect)    
        gc.PopState()

        dc2=wx.PaintDC(self)
        dc2.Blit(0,0,640,480,dc,0,0)
    def update(self,event):
        self.Refresh()

app = wx.App(False)
f=MainFrame(None,"Test")
app.MainLoop()

我写了这段代码来在一个面板上绘制双缓冲的图形内容,但窗口上总是有闪烁的现象。我尝试了不同的绘制方式,比如直线和曲线,但问题依然存在,我不知道是什么原因导致的。

2 个回答

1

如果你在使用比较现代的wxWidgets,可以用wx.BufferedPaintDC,这样就不用自己处理内存DC和绘图的麻烦了。而且在Windows系统上,使用FULL_REPAINT_ON_RESIZE这个选项,可能会导致闪烁,即使你没有调整窗口大小,这都是因为一些内部的奇怪情况。如果你不需要这个功能,试试NO_FULL_REPAINT_ON_RESIZE可能会有所帮助。否则,你可能需要简化一下你的代码,确保最简单的功能可以正常工作,另外可以看看wxpython.org上的DoubleBufferedDrawing维基页面。

2

你看到的闪烁是因为每次调用 Refresh() 时,背景会先被清空,然后再调用 onPaint。为了避免这种情况,你需要绑定到 EVT_ERASE_BACKGROUND,并让它什么都不做。

class DoubleBufferTest(wx.Panel):
    def __init__(self,parent=None,id=-1):
        # ... existing code ...
        self.Bind(wx.EVT_ERASE_BACKGROUND, self.onErase)
    def onErase(self, event):
        pass
    # ... existing code ...

撰写回答