Virgil Stokes | 8 Feb 23:37
Picon
Picon
Favicon
Gravatar

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

-- 
To unsubscribe, send email to wxPython-users+unsubscribe <at> googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en
'''
Purpose: to show how wx.Overlay() can be used to draw an object then erase it 
         (recover the bitmap before the object was drawn on it).

  This code snippet can be quite useful for the development of a more complex
  interactive drawing package.

 Notes:
  1. wx.ClientDC --- draws to window (frame) object, the interior (client part)
  2. wx.PaintDC  --- similiar to wx.ClientDC, but only used when processing a 
                     wx.PaintEvent
  3. Code is heavily commented for my own purposes.                   
  4. Code has been tested with Python 2.6.6, wxPython 2.8.12.1 on both a Windows
     Vista and 7 platform. No anomalies have been observed.
  5. TESTMODE = True, will "print" additional information for test purposes.   
  
  Creator: V. Stokes (vs <at> it.uu.se)
  Version: 2012.02.08.02
'''
(Continue reading)

Chris Barker | 9 Feb 19:29
Picon
Favicon

Re: Some code that could be helpful in using wx.Overlay

Hi,

On Wed, Feb 8, 2012 at 2:37 PM, Virgil Stokes <vs <at> it.uu.se> wrote:
> 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
(Continue reading)

Tim Roberts | 9 Feb 19:45

Re: Some code that could be helpful in using wx.Overlay

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 <at> probo.com
Providenza & Boekelheide, Inc.

--

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

Chris Barker | 9 Feb 20:20
Picon
Favicon

Re: Some code that could be helpful in using wx.Overlay

On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts <timr <at> 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?

(Continue reading)

Chris Barker | 9 Feb 20:34
Picon
Favicon

Re: Some code that could be helpful in using wx.Overlay

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 <at> noaa.gov> wrote:
> On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts <timr <at> 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.
>
(Continue reading)

Chris Barker | 9 Feb 20:34
Picon
Favicon

Re: Some code that could be helpful in using wx.Overlay

On Thu, Feb 9, 2012 at 11:34 AM, Chris Barker <chris.barker <at> 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 <at> noaa.gov> wrote:
>> On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts <timr <at> 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
(Continue reading)

Virgil Stokes | 10 Feb 11:36
Picon
Picon
Favicon
Gravatar

Re: Some code that could be helpful in using wx.Overlay

On 09-Feb-2012 20:34, Chris Barker wrote:
> On Thu, Feb 9, 2012 at 11:34 AM, Chris Barker<chris.barker <at> 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 <at> noaa.gov>  wrote:
>>> On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts<timr <at> 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:
(Continue reading)

Chris Barker | 10 Feb 18:50
Picon
Favicon

Re: Some code that could be helpful in using wx.Overlay

On Fri, Feb 10, 2012 at 2:36 AM, Virgil Stokes <vs <at> it.uu.se> wrote:
> 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(?)

(Continue reading)

Tim Roberts | 10 Feb 19:02

Re: Some code that could be helpful in using wx.Overlay

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 <at> probo.com
Providenza & Boekelheide, Inc.

--

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

Virgil Stokes | 10 Feb 20:25
Picon
Picon
Favicon
Gravatar

Re: Some code that could be helpful in using wx.Overlay

On 2012-02-10 18:50, Chris Barker wrote:
> On Fri, Feb 10, 2012 at 2:36 AM, Virgil Stokes<vs <at> it.uu.se>  wrote:
>> 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?
>
(Continue reading)

Tim Roberts | 10 Feb 20:34

Re: Some code that could be helpful in using wx.Overlay

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 <at> probo.com
Providenza & Boekelheide, Inc.
(Continue reading)

Kevin Ollivier | 12 Feb 21:30
Favicon

Re: Some code that could be helpful in using wx.Overlay

Hi Tim,

On Feb 10, 2012, at 11:34 AM, Tim Roberts 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.

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.
(Continue reading)

Tim Roberts | 13 Feb 19:46

Re: Some code that could be helpful in using wx.Overlay

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 <at> probo.com
Providenza & Boekelheide, Inc.

--

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

Chris Barker | 10 Feb 20:56
Picon
Favicon

Re: Some code that could be helpful in using wx.Overlay

On Fri, Feb 10, 2012 at 11:25 AM, Virgil Stokes <vs <at> it.uu.se> wrote:
> 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!

(Continue reading)

Chris Barker | 10 Feb 21:01
Picon
Favicon

Re: Some code that could be helpful in using wx.Overlay

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

--

-- 

Christopher Barker, Ph.D.
Oceanographer

(Continue reading)

Tim Roberts | 9 Feb 20:59

Re: Some code that could be helpful in using wx.Overlay

Chris Barker wrote:
> On Thu, Feb 9, 2012 at 10:45 AM, Tim Roberts <timr <at> probo.com> 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.

--

-- 
Tim Roberts, timr <at> probo.com
Providenza & Boekelheide, Inc.
(Continue reading)

Chris Barker | 10 Feb 18:07
Picon
Favicon

Re: Some code that could be helpful in using wx.Overlay

Tim,

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

> 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!)

(Continue reading)


Gmane