[wxPython] wxBufferedClientDC suggestion

First some background...

I've been working on a BitmapCanvas widget for PythonCard. Thanks to Chris
Barker's DrawCanvas example I was able to get something working pretty
quickly. In the last week I converted the turtle code in one of the
PythonCard samples into a turtle module with an AbstractTurtle and a
BitmapTurtle class. The BitmapTurtle class uses a BitmapCanvas, so I've
spent quite a bit of time dealing with offscreen bitmap issues.

The main purpose of the offscreen bitmap is to keep a copy of everything
drawn, so that as the window is minimized, obscured and resized, the bitmap
isn't lost. If used correctly, the offscreen bitmap can also reduce or
eliminate flicker of certain drawing operations. The downside in wxPython,
is that the management of the blitting needs to be done in Python and with
the additional overhead of needing to blit a bitmap after each draw
operation, using the offscreen buffer can be costly. Ideally, you only want
to blit the changed area or changed rect after each draw op with the option
of doing a series of drawing operations and then doing an explicit refresh
of the onscreen window.

After exchanging a few messages on wx-dev about possible helper routines I
came up with an idea for a wxPython wxBufferedClientDC class. The idea is to
have a subclass of wxClientDC that takes a wxMemoryDC as an additional
parameter. All the wxDC drawing methods work the same way, but instead of
drawing to the window, drawing is done to the wxMemoryDC passed in. An
autoRefresh parameter would indicate whether to blit from the wxMemoryDC
after each draw operation and there would be an additional method to force
an explicit refresh. The user code would keep the wxMemoryDC around for
other drawing operations, paint, and resize events. Buffered versions of
wxWindowDC and wxScreenDC could be done as well. The code would be C++, not
Python, so wxPython users wouldn't suffer a speed penalty.

I sent this suggestion to Robin, but it will just be another big item on his
to do list :slight_smile: What I'm wondering is whether anyone else on this list would
find this useful? Any other ideas on how to get the same functionality? I
may have been looking at this stuff too closely the last week and my brain
is just fogged.

Perhaps some people on the list familiar with the underlying wxWindows code
might even be able to do a patch that Robin could include in the
distribution? I don't program in C++, so I won't be of much use.

ka

Kevin Altis wrote:

After exchanging a few messages on wx-dev about possible helper routines I
came up with an idea for a wxPython wxBufferedClientDC class.

Kevin, have you seen Klass Kolwerda's Double Buffering DC??

http://www.xs4all.nl/~kholwerd/wxstuff/doublebuf/#general

IT may be just what you are looking for, and then it could be wrapped
for wxPython. Klass is very open to suggestions, and I get the feeeling
he'd really like to see some of his code used. The Double Buffering DC
is part of his wxCanbvas package, which is a zoomable, scallable, vector
drawing package.:

http://www.xs4all.nl/~kholwerd/wxstuff/canvas/

Another thing I'd like to see wrapped for wxPython.

I don't program in C++, so I won't be of much use.

Me neither, so I just sit and hope someone does what I want...

-Chris

···

--
Christopher Barker,
Ph.D.
ChrisHBarker@home.net --- --- ---
http://members.home.net/barkerlohmann ---@@ -----@@ -----@@
                                   ------@@@ ------@@@ ------@@@
Oil Spill Modeling ------ @ ------ @ ------ @
Water Resources Engineering ------- --------- --------
Coastal and Fluvial Hydrodynamics --------------------------------------
------------------------------------------------------------------------

> After exchanging a few messages on wx-dev about possible helper
routines I
> came up with an idea for a wxPython wxBufferedClientDC class.

Kevin, have you seen Klass Kolwerda's Double Buffering DC??

http://www.xs4all.nl/~kholwerd/wxstuff/doublebuf/#general

IT may be just what you are looking for, and then it could be wrapped
for wxPython. Klass is very open to suggestions, and I get the feeeling
he'd really like to see some of his code used. The Double Buffering DC
is part of his wxCanbvas package, which is a zoomable, scallable, vector
drawing package.:

http://www.xs4all.nl/~kholwerd/wxstuff/canvas/

Another thing I'd like to see wrapped for wxPython.

I just sent the email below...

···

-----Original Message-----
From: Kevin Altis [mailto:altis@semi-retired.com]
Sent: Monday, October 15, 2001 1:37 PM
To: klaas holwerda [kholwerd@xs4all.nl]
Subject: buffered bitmap drawing

Hi,
I'm the coordinator for the PythonCard project.
http://pythoncard.sourceforge.net/

I started a thread on the wxpython-users mailing list about buffered bitmap
drawing.

Chris Barker suggested I check out your page:
http://www.xs4all.nl/~kholwerd/wxstuff/doublebuf/

What I'm wondering is whether you are also a Python user or just C++? This
looks like a useful set of classes that would be nice to have in wxWindows
or wrapped in wxPython. My own solution which uses a wxMemoryDC does all its
drawing offscreen and then blits the changed rect. You can control whether
to auto update after each draw operation or blit at a later time. This still
works for interactive drawing and in fact for interactive use the overhead
of managing the wxMemoryDC doesn't present the performance issue that occurs
when you try and draw a lot of points, lines, etc. in a tight loop say for
plotting.

The problem is that the management must currently be done in Python which is
slow. Also, it doesn't help that wxWindows appears to be missing the
routines that indicate a "dirty" region or rect after each draw operation.
These routines are available AFAIK on Windows and the Mac and hopefully
Linux/GTK...

Anyway, this is just a hello. If you have any ideas for getting your stuff
into wxWindows, so that wxPython could then wrap it or suggestions on the
wxBufferedClientDC that I posted about, let me know. The only thing that I
would mention that wasn't in the original post is that it might make sense
to always sync blits on vertical refresh if that is possible under wxWindows
to avoid flashing.

ka
---
Kevin Altis
altis@semi-retired.com

After exchanging a few messages on wx-dev about possible helper routines I
came up with an idea for a wxPython wxBufferedClientDC class. The idea is

to

have a subclass of wxClientDC that takes a wxMemoryDC as an additional
parameter. All the wxDC drawing methods work the same way, but instead of
drawing to the window, drawing is done to the wxMemoryDC passed in. An
autoRefresh parameter would indicate whether to blit from the wxMemoryDC
after each draw operation and there would be an additional method to force
an explicit refresh. The user code would keep the wxMemoryDC around for
other drawing operations, paint, and resize events. Buffered versions of
wxWindowDC and wxScreenDC could be done as well. The code would be C++,

not

Python, so wxPython users wouldn't suffer a speed penalty.

A couple issues:

1. You don't want to hold on to the wxMemoryDC as DC's are a scarce resource
on windows. You would want to hold on to the wxBitmap and select it into a
new wxMemoryDC each time you need to draw to it.

2. Deriving from wxClientDC is probably not a good idea for the same reason
as above but also because will want it to interact with other DCs over time.
For example it is only with the wxPaintDC that you can get the update region
from the system, and that can really help you optimize redraws.

So an implementation that comes to mind is a class that doesn't neccessarily
derive from anything that contains a wxBitmap, reflects all DC method calls
to a wxMemoryDC with that bitmap selected into it, and has some extra
methods to help manage the whole thing such as

    SetSize(width, height)
    DrawTo(otherDC, src_rect_or_region=None, dest_rect=None)

etc.

···

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