removing pauses in paiting

I have a wx.Frame that has several wx.Panel's that do custom drawing. A
couple of them take a bit of time to draw. The result is that on a resize
(under windows), the various components update to the screen at different
times. This is pretty distracting ... and it results in some choppy looking
windows before the redraws complete (occurring over a couple of seconds).

Note: I am using a timer within the wx.EVT_SIZE event that only performs the
drawing if the resizing pauses long enough. But this is not the issue as
the choppy redraws occur regardless when the window finally gets its paint
events.

1. Do I have any control of how or when paint events are sent to the various
components in the frame? Since (to my understanding) wx.EVT_PAINT is not a
CommandEvent - they then do not propagate. Therefore, the underlying
platform must tell the top most window to paint ... and it must somehow send
out paint events throughout the hierarchy. This is a guess on my part ...
and am curious as to how the various paint events actually get generated and
distributed. (an explanation or a reference would be great as I have not
been able to understand this looking at references online)

2. I know that when using a BufferedDC ... it blits the buffer to the screen
when all references to the DC disappear. One idea that I had was to force
all of the draws to the screen at the very end. I would accomplish this by
storing dc's until all components were done drawing ... and then deleting
all of them in succession at the end. The challenge is how I would do this
easily and safely? All of the paint methods are distributed in several
places, I would need a central manager that would store and then delete
these. And worse yet - how would I know when all of the paint events were
finished? This seems like a bad approach. I know I have also seen warnings
against storing dcs as well. Is there any other way to get everything to go
to the screen at once? I want to get rid of all of the choppy arrivals from
the various components.

···

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/removing-pauses-in-paiting-tp4725598p4725598.html
Sent from the wxPython-users mailing list archive at Nabble.com.

Double buffering can be done internally by wx if you call SetDoubleBuffered(True)

···

On Tue, Aug 23, 2011 at 01:01, rocketman tobin@vanpelts.net wrote:

I have a wx.Frame that has several wx.Panel’s that do custom drawing. A

couple of them take a bit of time to draw. The result is that on a resize

(under windows), the various components update to the screen at different

times. This is pretty distracting … and it results in some choppy looking

windows before the redraws complete (occurring over a couple of seconds).

Note: I am using a timer within the wx.EVT_SIZE event that only performs the

drawing if the resizing pauses long enough. But this is not the issue as

the choppy redraws occur regardless when the window finally gets its paint

events.

  1. Do I have any control of how or when paint events are sent to the various

components in the frame? Since (to my understanding) wx.EVT_PAINT is not a

CommandEvent - they then do not propagate. Therefore, the underlying

platform must tell the top most window to paint … and it must somehow send

out paint events throughout the hierarchy. This is a guess on my part …

and am curious as to how the various paint events actually get generated and

distributed. (an explanation or a reference would be great as I have not

been able to understand this looking at references online)

  1. I know that when using a BufferedDC … it blits the buffer to the screen

when all references to the DC disappear. One idea that I had was to force

all of the draws to the screen at the very end. I would accomplish this by

storing dc’s until all components were done drawing … and then deleting

all of them in succession at the end. The challenge is how I would do this

easily and safely? All of the paint methods are distributed in several

places, I would need a central manager that would store and then delete

these. And worse yet - how would I know when all of the paint events were

finished? This seems like a bad approach. I know I have also seen warnings

against storing dcs as well. Is there any other way to get everything to go

to the screen at once? I want to get rid of all of the choppy arrivals from

the various components.

View this message in context: http://wxpython-users.1045709.n5.nabble.com/removing-pauses-in-paiting-tp4725598p4725598.html

Sent from the wxPython-users mailing list archive at Nabble.com.

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

Wow! I somehow missed that method. I guess I was too focused on double
buffering my individual dc's and did not realize you could get the native
platform to do it for the whole window!

Nothing like a single line of code to solve your problem ...

Thanks!

···

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/removing-pauses-in-paiting-tp4725598p4727164.html
Sent from the wxPython-users mailing list archive at Nabble.com.

If you need to support running on XP then you may still have problems there. The APIs that SetDoubleBuffered method uses are implemented there, but it does not work as well as with newer versions of Windows.

···

On 8/23/11 8:26 AM, rocketman wrote:

Wow! I somehow missed that method. I guess I was too focused on double
buffering my individual dc's and did not realize you could get the native
platform to do it for the whole window!

Nothing like a single line of code to solve your problem ...

--
Robin Dunn
Software Craftsman

Just as a follow up. I have placed a SetDoubleBuffer(True) at the top level
window. This does help the situation in terms of odd rendering and flickers
during the redraw. But it still does not completely accomplish the single
draw of the entire window at once.

To recap:

When a EVT_PAINT arrives on the top window and trickles down through all of
the sub windows I want the platform (win7) to buffer all of the paints and
then blit all of them to the screen at once at the end when done. The end
result should be a snappy draw of the result. The suggested
SetDoubleBuffer() trick makes it better - but sometimes it works and
sometimes it pauses slightly as different client areas hit the screen.

I am starting to think that win7 still gets hung up in this final blit at
times ... possibly dependent on what else is going on within its own que of
OS level activity. This just may be a level of control granularity that is
not easily achievable ...

···

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/removing-pauses-in-paiting-tp4725598p4735046.html
Sent from the wxPython-users mailing list archive at Nabble.com.

Just a conceptual nitpick, but paint events don't actually "trickle down" to all child windows. They are mostly independent and are sent only to those windows that have been marked as "damaged" by the system or because you've called Refresh. Doing a Refresh on a parent window does however also trigger a paint event for child windows, if they intersect the rectangle passed to Refresh (if any).

For best results in your program you should try to minimize the time it takes to execute your EVT_PAINT handlers. If the painting of one of the sub windows takes a "noticeable" amount of time to perform then that will block the processing of the paint events for the others that haven't been (re)painted yet, making the delay even more noticeable.

The best way to deal with that IMO is to keep your own buffer bitmap and reduce the EVT_PAINT handler to just a single Blit of that bitmap. (wx.BufferedDC and wx.BufferedPaintDC can help with that.) This way the actual update of the screen for each of the sub windows is very quick, fast enough that they will probably appear to the eye that they are all happening at the same time. This unfortunately means that you need to maintain the content of that buffer bitmap outside of the paint event handler, but if you were already using wx.ClientDC's for drawing outside of the paint event then you may already be half way there.

···

On 8/25/11 9:06 AM, rocketman wrote:

Just as a follow up. I have placed a SetDoubleBuffer(True) at the top level
window. This does help the situation in terms of odd rendering and flickers
during the redraw. But it still does not completely accomplish the single
draw of the entire window at once.

To recap:

When a EVT_PAINT arrives on the top window and trickles down through all of
the sub windows I want the platform (win7) to buffer all of the paints and
then blit all of them to the screen at once at the end when done. The end
result should be a snappy draw of the result. The suggested
SetDoubleBuffer() trick makes it better - but sometimes it works and
sometimes it pauses slightly as different client areas hit the screen.

I am starting to think that win7 still gets hung up in this final blit at
times ... possibly dependent on what else is going on within its own que of
OS level activity. This just may be a level of control granularity that is
not easily achievable ...

--
Robin Dunn
Software Craftsman

so in short: you need to think about your drawing, etc at a Window level, not a Frame level or Panel level.

For more detail on Double buffering, see:

http://wiki.wxpython.org/DoubleBufferedDrawing

-Chris

···

On 8/25/11 10:54 AM, Robin Dunn wrote:

Just a conceptual nitpick, but paint events don't actually "trickle
down" to all child windows. They are mostly independent

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Robin, Chris - Thanks.

I have tweaked a few things and now am getting the right single draw at once
in the end. I went back and reworked all of my paint methods.

Robin - Thanks for the conceptual nitpick on "trickle". I knew as I was
typing it - that it was a poor word :-). I am never sure what it is going on
behind the scenes ... more understanding of what is really going on behind
the scenes is great. Thanks for clarifying.

···

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/removing-pauses-in-paiting-tp4725598p4738930.html
Sent from the wxPython-users mailing list archive at Nabble.com.