Some code that could be helpful in using wx.Overlay

With the help of Tim Roberts I have prepared some code that I hope will be useful for those of you who would like to know more about wx.Overlay. The code contains many comments which IMHO can be helpful when working with wx.Overlay.

--V

EraseOverlayExampleE.py (6.44 KB)

Hi,

With the help of Tim Roberts I have prepared some code that I hope will be
useful for those of you who would like to know more about wx.Overlay. The
code contains many comments which IMHO can be helpful when working with
wx.Overlay.

THanks for the demo -- this would be a good thing to add to the Wiki.

However:

1) it crashes (after hanging a while) on OS-X, with:
  wxPython version: 2.8.12.1 (mac-unicode)

Enter OnPaint -- 1
Forced recovery of screen -- 1
Bus error

I took a look at the code, and it doen'st seem quite right -- creating
a ClientDC inside a Paint event doe snot seem like a good idea. And
I'm not sure what creating an Overlay, then tossing it out does for
you in the Paint handler.

In fact, I think you're still drawing with a ClientDC the outline -- I
think you're going at this in a far too complicated mannor -- TIm
explained what the overlay is doing internally, but you don't need to
work with that directly (recovering the bitmap -- in fact, I think
Overlays are supposed to be disposable -- create it, draw with hit,
toss it. If you want to "recover" a pre-draw bitmap, you should
probably store it in a wx.Bitmap yourself.

I've enclosed a version of your code that is simpler, and seems to
work fine (if I'm right about what you are trying to do), at least on
my machine.

I've also enclosed a demo I wrote a while back -- it uses an overlay
to draw a "rubber band box' on the Window -- the overlay allows you to
draw that box on top of the underlying window without re-drawing the
underlying contents as you do so. I"m pretty sure this has been tested
on OS-X, Windows and GTK, though it's been a while.

In general, I'm not sure your example is really what Overlays are for
-- they are ideal for drawing something rapidly changing on top of a
complex background -- in your demo case, the overlay does not change
with every mouse movement, but rather only when the mouse enters or
leave a box -- so you may be better off using a straight ClientDC,
perhaps with buffering the background, or just draw in the paintDC,
and have a flag that tells it which box outline to draw.

Thought the overlay is working fine, and your "real use case" may be
more complex and appropriate.

By the way if you are interested in this sorto f drawing stuff, you
may want to take a look at wx.lib.floatcanvas, though I haven't proper
use of Overlays in that -- it pre-dates that feature.

Overlaytest2.py (2.99 KB)

OverlayDemo.py (6.49 KB)

···

On Wed, Feb 8, 2012 at 2:37 PM, Virgil Stokes <vs@it.uu.se> wrote:

--

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

Chris Barker wrote:

I took a look at the code, and it doen'st seem quite right -- creating
a ClientDC inside a Paint event doe snot seem like a good idea. And
I'm not sure what creating an Overlay, then tossing it out does for
you in the Paint handler.

He doesn't -- he creates a wx.DCOverlay and tosses it out. That's the
usage model. The wx.Overlay holds the bitmap and has a long life. The
wx.DCOverlay controls access to the wx.Overlay, has no state, and is
intended to be short-lived.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

He doesn't -- he creates a wx.DCOverlay and tosses it out. That's the
usage model.

yup.

The wx.Overlay holds the bitmap and has a long life.

it does? wehre is that getting stored? is it a singleton under the
hood? I always figured the bitmap disappeared when the wx.DCOverlay
was destroyed. Indeed, I have a line of code in my examples, with the
comment:

        del odc # work around a bug in the Python wrappers to make
                # sure the odc is destroyed before the dc is.

but I guess that's just the DCOverlay getting destroyed.

The
wx.DCOverlay controls access to the wx.Overlay, has no state, and is
intended to be short-lived.

In any case, his code crashed on the Mac, and when i took out a lot of
that stuff, it seems to work fine.

It looks like Perhaps one is supposed to keep a reference to a
wx.Overlay around to recover the bitmap, but at least in the code
posted, that Overlay doesn't appear to be tied to a Window -- how
could you have a single fre-floating overlay?

Anyway, I can't find the docs for it, so I'm still a bit confused --
if you have time to edit that example to do what he's trying to do
correctly that would be great.

-Chris

···

On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts <timr@probo.com> wrote:

--

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

OK,

I"ve cleaned up the code a bit (enclosed), and it works fine on wxMac.

However, there is a possibility that a Paint event will mess up the
Overlay -- not sure about that, and on the Mac, I get few Paint
events -- OS-X double buffers Windows so even if I cover an uncover,
I'm not getting a paint event.

So someone please test on Windows and GTK, and see what we get.

-Chris

···

On Thu, Feb 9, 2012 at 11:20 AM, Chris Barker <chris.barker@noaa.gov> wrote:

On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts <timr@probo.com> wrote:

He doesn't -- he creates a wx.DCOverlay and tosses it out. That's the
usage model.

yup.

The wx.Overlay holds the bitmap and has a long life.

it does? wehre is that getting stored? is it a singleton under the
hood? I always figured the bitmap disappeared when the wx.DCOverlay
was destroyed. Indeed, I have a line of code in my examples, with the
comment:

   del odc \# work around a bug in the Python wrappers to make
           \# sure the odc is destroyed before the dc is\.

but I guess that's just the DCOverlay getting destroyed.

The
wx.DCOverlay controls access to the wx.Overlay, has no state, and is
intended to be short-lived.

In any case, his code crashed on the Mac, and when i took out a lot of
that stuff, it seems to work fine.

It looks like Perhaps one is supposed to keep a reference to a
wx.Overlay around to recover the bitmap, but at least in the code
posted, that Overlay doesn't appear to be tied to a Window -- how
could you have a single fre-floating overlay?

Anyway, I can't find the docs for it, so I'm still a bit confused --
if you have time to edit that example to do what he's trying to do
correctly that would be great.

-Chris

--

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

--

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

OK,

I"ve cleaned up the code a bit (enclosed)

oops -- here it is.

, and it works fine on wxMac.

OverlayDemo.py (5.22 KB)

···

On Thu, Feb 9, 2012 at 11:34 AM, Chris Barker <chris.barker@noaa.gov> wrote:

However, there is a possibility that a Paint event will mess up the
Overlay -- not sure about that, and on the Mac, I get few Paint
events -- OS-X double buffers Windows so even if I cover an uncover,
I'm not getting a paint event.

So someone please test on Windows and GTK, and see what we get.

-Chris

On Thu, Feb 9, 2012 at 11:20 AM, Chris Barker <chris.barker@noaa.gov> wrote:

On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts <timr@probo.com> wrote:

He doesn't -- he creates a wx.DCOverlay and tosses it out. That's the
usage model.

yup.

The wx.Overlay holds the bitmap and has a long life.

it does? wehre is that getting stored? is it a singleton under the
hood? I always figured the bitmap disappeared when the wx.DCOverlay
was destroyed. Indeed, I have a line of code in my examples, with the
comment:

   del odc \# work around a bug in the Python wrappers to make
           \# sure the odc is destroyed before the dc is\.

but I guess that's just the DCOverlay getting destroyed.

The
wx.DCOverlay controls access to the wx.Overlay, has no state, and is
intended to be short-lived.

In any case, his code crashed on the Mac, and when i took out a lot of
that stuff, it seems to work fine.

It looks like Perhaps one is supposed to keep a reference to a
wx.Overlay around to recover the bitmap, but at least in the code
posted, that Overlay doesn't appear to be tied to a Window -- how
could you have a single fre-floating overlay?

Anyway, I can't find the docs for it, so I'm still a bit confused --
if you have time to edit that example to do what he's trying to do
correctly that would be great.

-Chris

--

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

--

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

--

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

Chris Barker wrote:

The wx.Overlay holds the bitmap and has a long life.

it does? wehre is that getting stored? is it a singleton under the
hood? I always figured the bitmap disappeared when the wx.DCOverlay
was destroyed.

In the spirit of full disclosure, allow me to admit that everything I
know about wx.Overlay and wx.DCOverlay I learned this week by reading
the source code in response to Virgil's question. In the Windows
implementation, the bitmap is stored in the wx.Overlay.

It looks like Perhaps one is supposed to keep a reference to a
wx.Overlay around to recover the bitmap, but at least in the code
posted, that Overlay doesn't appear to be tied to a Window -- how
could you have a single fre-floating overlay?

You're right that it's not tied to a window. When you create a
wx.DCOverlay, you pass it a wx.Overlay and a DC. If that is the first
reference, the Overlay makes a copy of whatever surface is contained in
the DC into its bitmap. Later, when you call "clear", it copies the
bitmap back to the DC. That's really all it does in the Windows
implementation. It's a very small amount of code.

I understand that the Mac implementation uses some native APIs. I know
nothing about that.

···

On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts <timr@probo.com> wrote:

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

First, thanks Chris for your insights and modifications to the code.

I would like to point out that in my original posting there was a logical bug in the code (also in the code posted by Chris). That is, when the mouse moved from inside the cell grid to outside the cell grid, I should have returned and not tried to draw a rectangle. This logic error did not show up in the execution because the DrawRectangleRect returns with no exception if the rectangle passed is None.

I have now corrected this logic error, incorporated some of Chris Barker's changes, done some minor refactoring, and tried to improve the comments. To the wx.Python newbie (as I am), I strongly suggest that you experiment with this code (e.g. uncomment self.overlay.Reset(), add more cells to the cell grid, etc.)

Best regards and thanks for the help/suggestions :slight_smile:

--V

OverlayTest1.py (6.21 KB)

···

On 09-Feb-2012 20:34, Chris Barker wrote:

On Thu, Feb 9, 2012 at 11:34 AM, Chris Barker<chris.barker@noaa.gov> wrote:

OK,

I"ve cleaned up the code a bit (enclosed)

oops -- here it is.

, and it works fine on wxMac.

However, there is a possibility that a Paint event will mess up the
Overlay -- not sure about that, and on the Mac, I get few Paint
events -- OS-X double buffers Windows so even if I cover an uncover,
I'm not getting a paint event.

So someone please test on Windows and GTK, and see what we get.

-Chris

On Thu, Feb 9, 2012 at 11:20 AM, Chris Barker<chris.barker@noaa.gov> wrote:

On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts<timr@probo.com> wrote:

He doesn't -- he creates a wx.DCOverlay and tosses it out. That's the
usage model.

yup.

  The wx.Overlay holds the bitmap and has a long life.

it does? wehre is that getting stored? is it a singleton under the
hood? I always figured the bitmap disappeared when the wx.DCOverlay
was destroyed. Indeed, I have a line of code in my examples, with the
comment:

        del odc # work around a bug in the Python wrappers to make
                # sure the odc is destroyed before the dc is.

but I guess that's just the DCOverlay getting destroyed.

  The
wx.DCOverlay controls access to the wx.Overlay, has no state, and is
intended to be short-lived.

In any case, his code crashed on the Mac, and when i took out a lot of
that stuff, it seems to work fine.

It looks like Perhaps one is supposed to keep a reference to a
wx.Overlay around to recover the bitmap, but at least in the code
posted, that Overlay doesn't appear to be tied to a Window -- how
could you have a single fre-floating overlay?

Anyway, I can't find the docs for it, so I'm still a bit confused --
if you have time to edit that example to do what he's trying to do
correctly that would be great.

-Chris

--

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

--

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

Tim,

In the spirit of full disclosure, allow me to admit that everything I
know about wx.Overlay and wx.DCOverlay I learned this week by reading
the source code in response to Virgil's question.

there is not more authoritative way than that! For my part,
everything(not much) that I know, I learned by experimenting -- so I
have some idea what works, but am just guessing at the implementation.
Also, I use a Mac primarily, so the implementation is different
anyway, but the wx abstraction should be the same.

What I'm not clear on is how you can persist the Overlay through Paint
events -- wxMac doesn't call Paint often, so I couldn't' really test
with the example.

You're right that it's not tied to a window. When you create a
wx.DCOverlay, you pass it a wx.Overlay and a DC. If that is the first
reference, the Overlay makes a copy of whatever surface is contained in
the DC into its bitmap.

got it -- so the connection to a Window doesn't happen until you
connect it to a DC (and even then, it sound like it doesn't have to
know anything about the window -- only the DC and bitmap.

This sounds almost exactly like a wxBufferedDC, except that it's an
additional layer (overlay, after all!)

Now I'll poke at Virgil's code some more, and see what I can learn.

···

On Thu, Feb 9, 2012 at 11:59 AM, Tim Roberts <timr@probo.com> wrote:

--

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

I would like to point out that in my original posting there was a logical
bug in the code (also in the code posted by Chris).

odd -- it seemed to work fine -- though maybe I didn't know what is
was supposed to do.

I have now corrected this logic error, incorporated some of Chris Barker's
changes, done some minor refactoring, and tried to improve the comments. To
the wx.Python newbie (as I am), I strongly suggest that you experiment with
this code (e.g. uncomment self.overlay.Reset(), add more cells to the cell
grid, etc.)

well, this version crashes on the Mac -- darn! Ideally, that should
never happen, so it is a bug in wxPython -- but there should be a way
for it to work everywhere -- on to the debugging!

1) line 55:
    self.dcC = wx.ClientDC(self)

may be the source of the problem -- DCs are not designed to be
persisted -- you create one, draw with it, then delete it (or let
python delete it). So the ClientDC should be created when you need to
draw to the overlay -- i.e. in onMOuseMove.

2) lines 115 - 117:
           odc = wx.DCOverlay(self.overlay, self.dcC)
            odc.Clear()
            del odc # not sure if this is necessary(?)

I think you stil need the DCOverlay here -- in fact, deleting it here
is what's causing the crash on OS-X.

Though I'm confused -- we end up drawing to the wxClientDC - shouldn't
we be drawing to the Overlay? It looks like my mental model is wrong
here. Rather than there being a transparent overlay bitmap -- all
wxOverlay does is cache the Window contents, then you draw to the
ClientDC anyway. However, it's a bit different, as somehow what's been
draw to teh overlay stays there after Paint Events --a t least on The
Mac.

Try this on Windows:

1) re-size the Window to be smaller that the image -- so the edge of
the Window overlaps the right hand box.

2) move the mouse into the right box -- it should get highlighted

3) grab the corner of the window to resize it -- you never left the
box, so it shoujld stay highlighted.

4) the re-size causes Paint Events -- on my machine, the highlight
remains thought the Paint events -- but only on the part of the
rectangle that was exposed with the smaller window -- so the overlay
is persisting.

Is it the same on Windows?

To do this right, you'd need to bind the re-size events, and redraw
the overlay as well -- or, maybe better catch mouse leave event, and
clear the overlay there.

Anyway, I think the cause of the confusion is that Tim's explanation
of the implementation shifted focus away from the intent and API of an
Overlay -- which his really what you should be thinking about. The
intent is to have a surface that "overlays" the window on which you
can draw temporary stuff without having to re-draw the entire window
when that temporary stuff changes -- this is well suited to drawing
stuff that only exists on mouse mouse events, etc. -- your example
isn't quite that -- it is more like drawing the selection indicators
in a GUI -- which makes sense too -- the selection can change quickly,
and you may not want to re-draw the entire background each time.

So I think of an overlay as a clear piece of plastic sitting on top of
the window.

When you want to draw something, do you want to draw to that clear
layer on top, or draw to the main picture underneath? If the layer on
top, you use Overlay, if not then a regular ClientDC.

wx.DCOverlay.clear() does just what you'd think -- clears off that
clear piece of plastic, so you can draw something new on it. The rest
of the regular DC drawing functions draw to the clear piece of
plastic.

Though It seems I still don't have it quite right.

Updated code enclosed does this work on Windows?

-Chris

OverlayTest3.py (5.8 KB)

···

On Fri, Feb 10, 2012 at 2:36 AM, Virgil Stokes <vs@it.uu.se> wrote:

Best regards and thanks for the help/suggestions :slight_smile:

--V

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

--

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

Chris Barker wrote:

Though I'm confused -- we end up drawing to the wxClientDC - shouldn't
we be drawing to the Overlay? It looks like my mental model is wrong
here. Rather than there being a transparent overlay bitmap -- all
wxOverlay does is cache the Window contents, then you draw to the
ClientDC anyway.

Yes. The overlay is really more of a "drawing checkpoint". You do all
of your drawing to the normal DC, but the overlay lets you roll back the
window to some previous state, repeatedly.

It's a hacky solution to a difficult problem.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

I would like to point out that in my original posting there was a logical
bug in the code (also in the code posted by Chris).

odd -- it seemed to work fine -- though maybe I didn't know what is
was supposed to do.

I have now corrected this logic error, incorporated some of Chris Barker's
changes, done some minor refactoring, and tried to improve the comments. To
the wx.Python newbie (as I am), I strongly suggest that you experiment with
this code (e.g. uncomment self.overlay.Reset(), add more cells to the cell
grid, etc.)

well, this version crashes on the Mac -- darn! Ideally, that should
never happen, so it is a bug in wxPython -- but there should be a way
for it to work everywhere -- on to the debugging!

1) line 55:
     self.dcC = wx.ClientDC(self)

may be the source of the problem -- DCs are not designed to be
persisted -- you create one, draw with it, then delete it (or let
python delete it). So the ClientDC should be created when you need to
draw to the overlay -- i.e. in onMOuseMove.

Yes, I agree Chris --- this was not a good idea (will be fixed). I will try to extend my example --- but need a little more time (I am now in my 10th day of wxPython -- which I like very much).

By the way, a question for you --- Can wxPython be used for graphical output without using the wx.EVT_PAINT?

2) lines 115 - 117:
            odc = wx.DCOverlay(self.overlay, self.dcC)
             odc.Clear()
             del odc # not sure if this is necessary(?)

I think you stil need the DCOverlay here -- in fact, deleting it here
is what's causing the crash on OS-X.

Though I'm confused -- we end up drawing to the wxClientDC - shouldn't
we be drawing to the Overlay? It looks like my mental model is wrong
here. Rather than there being a transparent overlay bitmap -- all
wxOverlay does is cache the Window contents, then you draw to the
ClientDC anyway. However, it's a bit different, as somehow what's been
draw to teh overlay stays there after Paint Events --a t least on The
Mac.

Try this on Windows:

1) re-size the Window to be smaller that the image -- so the edge of
the Window overlaps the right hand box.

2) move the mouse into the right box -- it should get highlighted

3) grab the corner of the window to resize it -- you never left the
box, so it shoujld stay highlighted.

4) the re-size causes Paint Events -- on my machine, the highlight
remains thought the Paint events -- but only on the part of the
rectangle that was exposed with the smaller window -- so the overlay
is persisting.

Is it the same on Windows?

To do this right, you'd need to bind the re-size events, and redraw
the overlay as well -- or, maybe better catch mouse leave event, and
clear the overlay there.

Anyway, I think the cause of the confusion is that Tim's explanation
of the implementation shifted focus away from the intent and API of an
Overlay -- which his really what you should be thinking about. The
intent is to have a surface that "overlays" the window on which you
can draw temporary stuff without having to re-draw the entire window
when that temporary stuff changes -- this is well suited to drawing
stuff that only exists on mouse mouse events, etc. -- your example
isn't quite that -- it is more like drawing the selection indicators
in a GUI -- which makes sense too -- the selection can change quickly,
and you may not want to re-draw the entire background each time.

You might try a rather novel application of the code I posted --- a visual indicator of cells visited by the mouse. This is easily accomplished by uncommenting the self.overlay.Reset(). Of course, I am not recommending this approach for such a task; but, IMHO it can be helpful in learning more about Overlay.

So I think of an overlay as a clear piece of plastic sitting on top of
the window.

When you want to draw something, do you want to draw to that clear
layer on top, or draw to the main picture underneath? If the layer on
top, you use Overlay, if not then a regular ClientDC.

wx.DCOverlay.clear() does just what you'd think -- clears off that
clear piece of plastic, so you can draw something new on it. The rest
of the regular DC drawing functions draw to the clear piece of
plastic.

Though It seems I still don't have it quite right.

Updated code enclosed does this work on Windows?

No Chris, unfortunately it does not

UnboundLocalError: local variable 'odc' referenced before assignment

Best regards,
--V

···

On 2012-02-10 18:50, Chris Barker wrote:

On Fri, Feb 10, 2012 at 2:36 AM, Virgil Stokes<vs@it.uu.se> wrote:

Virgil Stokes wrote:

Yes, I agree Chris --- this was not a good idea (will be fixed). I will
try to extend my example --- but need a little more time (I am now in my
10th day of wxPython -- which I like very much).

By the way, a question for you --- Can wxPython be used for graphical
output without using the wx.EVT_PAINT?

This is more of a fundamental question about modern user interfaces than
it is about wxPython.

You can actually do your drawing wherever you want. The problem is that
your window can get covered up partly or wholly by other windows at any
time. When your window gets partly covered, the pixels that used to be
there simply do not exist any more. There is no magical warehouse where
the pixels you drew get saved. They are lost. So, when your window
comes to the top again, someone has to restore those pixels so the
window looks right. That's what the paint message is for.

All UI applications on all of the operating systems are supposed to be
able to restore their windows to their "current state" in response to
the paint event. Because of that, in many circumstances it is easier to
put all of the drawing in the EVT_PAINT handler, and when other
functions make changes that need new drawing, just have them Invalidate
the window to trigger a paint event.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

By the way, a question for you --- Can wxPython be used for graphical output
without using the wx.EVT_PAINT?

not sure what you mean exactly -- but I think the answer is no --
EVT_PAINT is where your code draws what's in the Window -- in theory,
you could do it all in ClientDCS on other events, but the Paint event
happens whenever the system knows that the Window needs to be (or
might need to be) re-painted, so you really need to do something with
it.

In fact, the recommendation these days is that all your drawing
happens in a paint event -- if there are times when your program needs
to change what's painted, it can call Update() to force a paint event.

You might try a rather novel application of the code I posted --- a visual
indicator of cells visited by the mouse. This is easily accomplished by
uncommenting the self.overlay.Reset().

I'm not using Reset() at all -- maybe a Mac-Windows difference?

Updated code enclosed does this work on Windows?

No Chris, unfortunately it does not

UnboundLocalError: local variable 'odc' referenced before assignment

darn -- my mistake -- I dont' think that's a Mac-Windows difference,
just me enclosing before a save!

try this one.

-Chris

OverlayTest3.py (5.91 KB)

···

On Fri, Feb 10, 2012 at 11:25 AM, Virgil Stokes <vs@it.uu.se> wrote:

--

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

Something new:

This jsut seemed to complicated -- I wasn't sure of the benefit.

So I re-did just using plain old paint event handlers.

IN the pain event, if the mouse is in a cell, then the highlight is
drawn, otherwise not.

in the mouse move handler, we check if the mouse has moved into or out
of cell, and if so, force a paint event.

That's it -- I'm having trouble seeing what the Overly is buying us.
And this version handle window re-sizing as it should, too.

If the background drawing was time consuming, then I'd double buffer
that, but otherwise wouldn't need to do anything else.

I do think Overlays are helpful for some other cases, particularly
when you want something drawn on every mouse move -- and don't want it
draw when the mouse leaves -- like the bubber-band box in my example I
posted earlier.

-Chris

OverlayNotTest.py (5.63 KB)

···

--

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

Hi Tim,

Virgil Stokes wrote:

Yes, I agree Chris --- this was not a good idea (will be fixed). I will
try to extend my example --- but need a little more time (I am now in my
10th day of wxPython -- which I like very much).

By the way, a question for you --- Can wxPython be used for graphical
output without using the wx.EVT_PAINT?

This is more of a fundamental question about modern user interfaces than
it is about wxPython.

You can actually do your drawing wherever you want. The problem is that
your window can get covered up partly or wholly by other windows at any
time. When your window gets partly covered, the pixels that used to be
there simply do not exist any more. There is no magical warehouse where
the pixels you drew get saved. They are lost. So, when your window
comes to the top again, someone has to restore those pixels so the
window looks right. That's what the paint message is for.

That's actually how Windows works, because the model is that pixels are drawn straight to the screen. On Mac, and possibly under GTK when using compositing window managers, this is not the case.

This is why, for example, Windows often needs you to use wx.BufferedPaintDC to avoid flicker, but Mac and Linux do not. (And why we have wx.AutoBufferedPaintDC to encapsulate the differences.) The other platforms are already drawing to an offscreen bitmap and then blitting to the display later.

Because they do not draw directly to the screen, the tricks you might use a wx.ClientDC for don't quite work as they should. It seems like GTK has some hacks to keep things working, but Mac does not. wx.ClientDC support on Mac is a huge hack and it actually in most cases causes serious problems with Mac applications.

All UI applications on all of the operating systems are supposed to be
able to restore their windows to their "current state" in response to
the paint event. Because of that, in many circumstances it is easier to
put all of the drawing in the EVT_PAINT handler, and when other
functions make changes that need new drawing, just have them Invalidate
the window to trigger a paint event.

It is not only easier, it simply will not work to do it otherwise on some platforms like Mac. Doing wx.ClientDC drawing on the Mac, for example, causes the entire display pipeline to be flushed and immediately redrawn, which is a very expensive operation. Do this repeatedly, and your app (and the OS) will appear to be frozen as it spends all its time trying to do paints. I actually think that making wx.ClientDC work on Mac (and keeping it working) was a mistake, as most people think it just works fine there since it is 'supported' and wx.ClientDC is shown and documented as a safe, cross-platform API.

EVT_PAINT is the only safe and efficient place to do drawing if you want your app to work cross-platform. "Rubber banding" is the only wx.ClientDC drawing operation I know of that is not possible to do in EVT_PAINT, and that's why we have wx.Overlay(DC).

Regards,

Kevin

···

On Feb 10, 2012, at 11:34 AM, Tim Roberts wrote:

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

Kevin Ollivier wrote:

That's actually how Windows works, because the model is that pixels are drawn straight to the screen. On Mac, and possibly under GTK when using compositing window managers, this is not the case.

Right -- things are also different on any X system that uses backing
store (few do), and on Vista and Windows 7 systems using the Aero Glass
interface, which is essentially a compositing window manager. Even on a
compositing system, you still get issues with parts of your own window
overlapping.

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.