wx.Overlay

125 views
Skip to first unread message

Robin Dunn

unread,
Dec 19, 2007, 3:25:02 PM12/19/07
to wxPytho...@lists.wxwidgets.org
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!

test_Overlay.py

Chris Mellon

unread,
Dec 19, 2007, 4:01:47 PM12/19/07
to wxPytho...@lists.wxwidgets.org
> 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

Robin Dunn

unread,
Dec 19, 2007, 6:52:34 PM12/19/07
to wxPytho...@lists.wxwidgets.org
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...)

steve

unread,
Sep 23, 2016, 8:15:41 AM9/23/16
to wxPython-users, wxPytho...@lists.wxwidgets.org
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

Robin Dunn

unread,
Oct 4, 2016, 6:36:11 PM10/4/16
to wxpytho...@googlegroups.com
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.

efahl

unread,
Oct 5, 2016, 8:32:11 PM10/5/16
to wxPython-users
wx.BufferedPainDC

Freudian slip?  :) 
Reply all
Reply to author
Forward
0 new messages