wx.Overlay

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

wx.Overlay

Robin Dunn
Hi all,

A while back I promised an example of using the wx.Overlay to assist
with drawing temporary things like rubber-band boxes over the top of
something else.  I finally did that this morning and I've attached the
result.  Basically instead of using the wx.INVERT or wx.XOR trick of
drawing a 2nd time to "erase" the rectangle, you can draw whatever you
want, in any colour you want, and you don't have to rely on a
side-effect of the logical op to make it work.

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


"""
A simple sample of using a wx.Overlay to draw a rubberband effect
"""

import wx
print wx.version()

class TestPanel(wx.Panel):
    def __init__(self, *args, **kw):
        wx.Panel.__init__(self, *args, **kw)

        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.Bind(wx.EVT_MOTION, self.OnMouseMove)

        self.startPos = None
        self.overlay = wx.Overlay()
       

    def OnPaint(self, evt):
        # Just some simple stuff to paint in the window for an example
        dc = wx.PaintDC(self)
        coords = ((40,40),(200,220),(210,120),(120,300))
        dc.SetBackground(wx.Brush("sky blue"))
        dc.Clear()
        dc.SetPen(wx.Pen("red", 2))
        dc.SetBrush(wx.CYAN_BRUSH)
        dc.DrawPolygon(coords)
        dc.DrawLabel("Draw the mouse across this window to see \n"
                    "a rubber-band effect using wx.Overlay",
                    (140, 50, -1, -1))
       

    def OnLeftDown(self, evt):
        # Capture the mouse and save the starting posiiton for the
        # rubber-band
        self.CaptureMouse()
        self.startPos = evt.GetPosition()


    def OnMouseMove(self, evt):
        if evt.Dragging() and evt.LeftIsDown():
            rect = wx.RectPP(self.startPos, evt.GetPosition())
           
            # Draw the rubber-band rectangle using an overlay so it
            # will manage keeping the rectangle and the former window
            # contents separate.
            dc = wx.ClientDC(self)
            odc = wx.DCOverlay(self.overlay, dc)
            odc.Clear()
           
            dc.SetPen(wx.Pen("black", 2))
            if 'wxMac' in wx.PlatformInfo:
                dc.SetBrush(wx.Brush(wx.Colour(0xC0, 0xC0, 0xC0, 0x80)))
            else:
                dc.SetBrush(wx.TRANSPARENT_BRUSH)
            dc.DrawRectangleRect(rect)

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


    def OnLeftUp(self, evt):
        if self.HasCapture():
            self.ReleaseMouse()
        self.startPos = None

        # When the mouse is released we reset the overlay and it
        # restores the former content to the window.
        dc = wx.ClientDC(self)
        odc = wx.DCOverlay(self.overlay, dc)
        odc.Clear()
        del odc
        self.overlay.Reset()

           

app = wx.App(redirect=False)
frm = wx.Frame(None, title="wx.Overlay Test", size=(450,450))
pnl = TestPanel(frm)
frm.Show()
app.MainLoop()
Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

Chris Mellon
On Dec 19, 2007 2:25 PM, Robin Dunn <[hidden email]> wrote:

> Hi all,
>
> A while back I promised an example of using the wx.Overlay to assist
> with drawing temporary things like rubber-band boxes over the top of
> something else.  I finally did that this morning and I've attached the
> result.  Basically instead of using the wx.INVERT or wx.XOR trick of
> drawing a 2nd time to "erase" the rectangle, you can draw whatever you
> want, in any colour you want, and you don't have to rely on a
> side-effect of the logical op to make it work.
>
> --
> Robin Dunn
> Software Craftsman
> http://wxPython.org  Java give you jitters?  Relax with wxPython!
>
>
> """
> A simple sample of using a wx.Overlay to draw a rubberband effect
> """
>
> import wx
> print wx.version()
>
> class TestPanel(wx.Panel):
>     def __init__(self, *args, **kw):
>         wx.Panel.__init__(self, *args, **kw)
>
>         self.Bind(wx.EVT_PAINT, self.OnPaint)
>         self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
>         self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
>         self.Bind(wx.EVT_MOTION, self.OnMouseMove)
>
>         self.startPos = None
>         self.overlay = wx.Overlay()
>
>
>     def OnPaint(self, evt):
>         # Just some simple stuff to paint in the window for an example
>         dc = wx.PaintDC(self)
>         coords = ((40,40),(200,220),(210,120),(120,300))
>         dc.SetBackground(wx.Brush("sky blue"))
>         dc.Clear()
>         dc.SetPen(wx.Pen("red", 2))
>         dc.SetBrush(wx.CYAN_BRUSH)
>         dc.DrawPolygon(coords)
>         dc.DrawLabel("Draw the mouse across this window to see \n"
>                     "a rubber-band effect using wx.Overlay",
>                     (140, 50, -1, -1))
>
>
>     def OnLeftDown(self, evt):
>         # Capture the mouse and save the starting posiiton for the
>         # rubber-band
>         self.CaptureMouse()
>         self.startPos = evt.GetPosition()
>
>
>     def OnMouseMove(self, evt):
>         if evt.Dragging() and evt.LeftIsDown():
>             rect = wx.RectPP(self.startPos, evt.GetPosition())
>
>             # Draw the rubber-band rectangle using an overlay so it
>             # will manage keeping the rectangle and the former window
>             # contents separate.
>             dc = wx.ClientDC(self)
>             odc = wx.DCOverlay(self.overlay, dc)
>             odc.Clear()
>
>             dc.SetPen(wx.Pen("black", 2))
>             if 'wxMac' in wx.PlatformInfo:
>                 dc.SetBrush(wx.Brush(wx.Colour(0xC0, 0xC0, 0xC0, 0x80)))
>             else:
>                 dc.SetBrush(wx.TRANSPARENT_BRUSH)
>             dc.DrawRectangleRect(rect)
>
>             del odc # work around a bug in the Python wrappers to make
>                     # sure the odc is destroyed before the dc is.
>
>
>     def OnLeftUp(self, evt):
>         if self.HasCapture():
>             self.ReleaseMouse()
>         self.startPos = None
>
>         # When the mouse is released we reset the overlay and it
>         # restores the former content to the window.
>         dc = wx.ClientDC(self)
>         odc = wx.DCOverlay(self.overlay, dc)
>         odc.Clear()
>         del odc
>         self.overlay.Reset()
>
>
>
> app = wx.App(redirect=False)
> frm = wx.Frame(None, title="wx.Overlay Test", size=(450,450))
> pnl = TestPanel(frm)
> frm.Show()
> app.MainLoop()
>

Attached is a similar example that uses wxGraphicsContext to get an
alpha-blended selection rect, and includes a hack to work around
flicker on MSW.

overlay.py (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

Chris Barker - NOAA Federal
In reply to this post by Robin Dunn
Robin Dunn wrote:
> A while back I promised an example of using the wx.Overlay to assist
> with drawing temporary things like rubber-band boxes over the top of
> something else.

Very nice!

And right after you fixed the wx.XOR bug!

This still appears to use a wx.ClientDC. Does it not suffer from the
issues with that we discussed a little while back?

In any case, it's prettier and easier to use.

 > in any colour you want,

This is still an issue -- if you don't know what colors may be on the
screen, how do you make sure to get a contrasting color (at least
without alpha, which, from your code, only appears to work on the Mac)?

-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

[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

Chris Barker - NOAA Federal
In reply to this post by Chris Mellon
Chris Mellon wrote:

> Attached is a similar example that uses wxGraphicsContext to get an
> alpha-blended selection rect, and includes a hack to work around
> flicker on MSW.

Tested on OS-X (10.4, PPC), wxPython version: 2.8.7.2.20071217

It doesn't work, then crashes with a bus error.

No time to try to isolate the problem now.

-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

[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

Robin Dunn
In reply to this post by Chris Barker - NOAA Federal
Christopher Barker wrote:

> Robin Dunn wrote:
>> A while back I promised an example of using the wx.Overlay to assist
>> with drawing temporary things like rubber-band boxes over the top of
>> something else.
>
> Very nice!
>
> And right after you fixed the wx.XOR bug!
>
> This still appears to use a wx.ClientDC. Does it not suffer from the
> issues with that we discussed a little while back?

My understanding is that it doesn't.  On Mac it is actually using an
overlay object provided by the platform, and the client DC is just used
to get the plumbing right.  (So it is actually as if it was drawing on a
piece of transparent glass above the window, instead of on the window
itself.)  On the other platforms the client dc is used directly to
implement a similar behavior.


>
> In any case, it's prettier and easier to use.
>
>  > in any colour you want,
>
> This is still an issue -- if you don't know what colors may be on the
> screen, how do you make sure to get a contrasting color (at least
> without alpha, which, from your code, only appears to work on the Mac)?

Using a plain DC you can only use Alpha on the Mac, but as the other
Chris showed us you can use a wx.GraphicsContext (or a wx.GCDC) to get
alpha everywhere.  (Although I'm seeing a crash currently on the Mac
when trying to use a GC with an Overlay, so I'll need to investigate
that...)


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


Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

Chris Barker - NOAA Federal
Robin Dunn wrote:
>> This still appears to use a wx.ClientDC. Does it not suffer from the
>> issues with that we discussed a little while back?
>
> My understanding is that it doesn't.

Cool, 'cause I experimented with doing away with ClientDC and just
calling Refresh(), and doing all the drawing in the PAINT handler. It
worked great on the Mac, but not so well elsewhere - if there where
event sin the queue at all, things got slow.

For this kind of thing I really do want "draw this now!".

This Overlay thing might be a good way to go though. 2.8 only, I assume?

> Using a plain DC you can only use Alpha on the Mac, but as the other
> Chris showed us you can use a wx.GraphicsContext (or a wx.GCDC) to get
> alpha everywhere.  (Although I'm seeing a crash currently on the Mac

yeah, me too.

> when trying to use a GC with an Overlay, so I'll need to investigate
> that...)

I look forward to what you find.

-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

[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

Robin Dunn
Christopher Barker wrote:
> Robin Dunn wrote:

> This Overlay thing might be a good way to go though. 2.8 only, I assume?
>

Yes, I think it was added in a late 2.7 or early 2.8 release.

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


Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

steve
In reply to this post by Robin Dunn
Hi Robin,
 
Your sample code doesn't work when Double Buffering is turned on. Is there a workaround without turning double buffering off?
 
Best Regards

On Wednesday, December 19, 2007 at 10:25:02 PM UTC+2, Robin Dunn wrote:
Hi all,

A while back I promised an example of using the wx.Overlay to assist
with drawing temporary things like rubber-band boxes over the top of
something else.  I finally did that this morning and I've attached the
result.  Basically instead of using the wx.INVERT or wx.XOR trick of
drawing a 2nd time to "erase" the rectangle, you can draw whatever you
want, in any colour you want, and you don't have to rely on a
side-effect of the logical op to make it work.

--
Robin Dunn
Software Craftsman
<a onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2FwxPython.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHG9kM-NEpJfIvl_lWJvA23SuLjOA&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2FwxPython.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHG9kM-NEpJfIvl_lWJvA23SuLjOA&#39;;return true;" href="http://wxPython.org" target="_blank" rel="nofollow">http://wxPython.org  Java give you jitters?  Relax with wxPython!

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

Robin Dunn
steve wrote:
Hi Robin,
 
Your sample code doesn't work when Double Buffering is turned on. Is there a workaround without turning double buffering off?
 

The current version of that sample is here: https://github.com/wxWidgets/wxPython/blob/master/sandbox/test_Overlay.py although it doesn't address dealing with double buffering.  I expect that you are on Windows, correct?  The way it does the built-in automatic double buffering is a little bassackwards and tends to cause squirrelly problems in some corner cases. I've usually had better results with managing the buffering myself by keeping a buffer bitmap and using a wx.BufferedPainDC in the EVT_PAINT handler.  I expect that with that technique and also using an overlay for your rubberband would work fine.


--
Robin Dunn
Software Craftsman
http://wxPython.org

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: wx.Overlay

efahl
wx.BufferedPainDC

Freudian slip?  :) 

--
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 [hidden email].
For more options, visit https://groups.google.com/d/optout.