Re: Drawing outside of an event handler wx.EVT_PAINT

Tim Roberts <[email protected]> Wed, 9 Dec 2020 09:51:18 -0800
Newsgroups gmane.comp.python.wxpython
Organization Providenza & Boekelheide, Inc.
Message-ID <[email protected]>
ioprst wrote:
>
> I need to draw a grid in the cells of which images will be located 
> (wx.Bitmap).
>
> When you click on a cell, the cursor (orange square) should draw above it.
>
> Since the wx.EVT_PAINT handler will need to draw quite a lot, it was 
> decided to draw the cursor using wx.ClientDC, when the user selects a 
> cell, and through wx.PaintDC, when the full redraw is called 
> (self.DrawCursor(dc) in OnPaint).

I don't claim that I have the answers, but let me point this out.  The 
two solutions you propose (drawing with ClientDC in mouse handler vs 
doing a refresh and drawing during onPaint) involve exactly the same 
amount of drawing.  You're not saving any drawing time.  In FACT, the 
refresh/onPaint solution is usually MORE efficient, because the system 
will coalesce multiple refresh calls so you don't waste time drawing 
multiple times before the screen can even display it.

To add to the efficiency, remember that you can pass a rectangle to 
Refresh, to tell the system "this is the dirty region that needs to be 
painted".  One of the differences between a wxPaintDC and a wxClientDC 
is that the paint DC establishes a "clipping region" that only includes 
the dirty regions.  Drawing you do outside that area becomes a quick no-op.

As a general rule (and it's not ALWAYS true), if you can arrange things 
so that all of your drawing is done in a paint handler, your application 
will perform better.  If you need this to be cross-platform, MacOS is 
considering changes that would make it impossible to draw outside of a 
paint handler, but that's still in the future.


> My problem is that when I draw a new cursor, the old one is not 
> removed until the wx.EVT_PAINT handler is called.

The only alternative is to simulate the double-buffering yourself -- 
keep a bitmap of what the screen SHOULD look like, and restore the old 
region when you draw the new cursor.


> Using self.SetDoubleBuffered (True) solves my problem, but it results 
> in the wx.EVT_PAINT handler being called every time the cell is 
> clicked, which leads to a large extra computational cost, since I only 
> need to redraw the cursor (and the function draw cursor is called twice).

How much drawing are you doing?  Cells don't get clicked very often.  
It's very difficult for me to imagine a situation where drawing during a 
cell click would have any measurable impact on application performance.

-- 
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.


-- 
You received this message because you are subscribed to the Google Groups "wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion on the web visit https://groups.google.com/d/msgid/wxpython-users/5a768152-a4ea-2ea7-c4d6-f8ea88724fdd%40probo.com.
smime.p7s (application/pkcs7-signature, 3.3 KB) - not displayed