views:

141

answers:

2
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()

I've come up with this code to draw double buffered GraphicsContext content onto a panel, but there's a constant flickering across the window. I've tried different kinds of paths, like lines and curves but it's still there and I don't know what's causing it.

A: 

If you're using a relatively modern wxWidgets, you can use wx.BufferedPaintDC and avoid having to muck around with the memory DC and painting and blitting on your own. Also, on windows, FULL_REPAINT_ON_RESIZE often causes flickering even when you're not resizing the window due to funny things going on under the covers - if you don't need it, going with NO_FULL_REPAINT_ON_RESIZE may help. Otherwise, you'll want to simplify your code some to make sure you can get the simplest thing to work, and perhaps take a look at the DoubleBufferedDrawing wiki page at wxpython.org.

Nick Bastin
Changing FULL_REPAINT_ON_RESIZE doesn't help, and I think this is the simplest application that shows my problem while still being runnable. I'm going over the DoubleBufferedDrawing page but the buffering itself seems to work fine (full screen flickering isn't there anymore)
Bibendum
+1  A: 

You get flicker because each Refresh() causes the background to get erased before calling onPaint. You need to bind to EVT_ERASE_BACKGROUND and make it a no-op.

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 ...
FogleBird