[wxPython-users] Not quite understanding buffered DCs

Robin Dunn robin at alldunn.com
Tue Dec 26 12:16:11 PST 2006


Jeffrey Barish wrote:
> I understand the principle behind buffered DCs: A buffered DC reduces
> flicker by accumulating the effects of many draw commands before blitting
> the final result to the screen in one operation.  In Listing 6.1 of the
> book, there is a buffered DC for DrawLines and another for drawMotion to
> accumulate the effect of many DrawLine commands.  But doesn't the actual
> drawing to the screen occur in OnPaint?  

You can also paint outside of a EVT_PAINT handler by using a 
wx.ClientDC[1].  In the example in the book this is what is done in 
OnMotion.  The new lines are drawn to the buffer and then the buffer 
will be flushed to the wx.ClientDC.


> Isn't the drawing of individual
> elements already done by the time we get here?  I'm thinking that the
> individual elements have already been rendered into the bitmap buffer, so
> the only thing that needs to happen in OnPaint is a blit of the bitmap to
> the screen.

True.

>  No flicker there because everything gets drawn to the screen
> in one operation.  I am thinking that the bitmap buffer provides the
> necessary buffering.  Maybe I am confused about what the bitmap buffer
> does.

I think you've got a good handle on it.

> 
> Moreover, it seems as if we don't really need a BufferedPaintDC in OnPaint,
> aside from the convenience of not having to spell out the blit operation,
> again because the screen update happens as the result of one blit
> operation.

It is all for convenience.  That one line in the example replaces about 
4 lines it would take to do it without a wx.BufferedPaintDC.  In fact, 
all of the buffered dc classes are entirely for convenience.  You can do 
everything they do yourself with just a bitmap, a MemoryDC and a 
ClientDC or PaintDC.

> I can see a use for BufferedPaintDC in a program where all the drawing takes
> place in OnPaint.  Without the buffering, individual elements would appear
> sequentially.  But if the drawing is already done by the time we get to
> OnPaint, isn't the buffering superfluous?

I think what you are still missing is that:

1. There still needs to be a wx.PaintDC created, otherwise nothing will 
be painted at all.  The wx.BufferedPaintDC creates a wx.PaintDC 
internally for you.

2. A side effect of creating a buffered dc is that the buffer bitmap 
will be flushed to the real dc when the buffered dc is garbage collected.

So "wx.BufferedPaintDC(self, self.buffer)" will actually create a 
PaintDC and a MemoryDC, select the bitmap into the memory DC and then 
blit the memory DC to the paint DC.




[1] Although it is becoming a better practice to avoid using wx.ClientDC 
and just call Refresh instead, and do all your painting from the 
EVT_PAINT handler.  This is because with the newer CoreGraphics API on 
OS X "out of order repaints" is much more expensive of an operation. 
It's possible that other platforms may move in this direction as well.

-- 
Robin Dunn
Software Craftsman
http://wxPython.org  Java give you jitters?  Relax with wxPython!





More information about the wxpython-users mailing list