8 Feb 23:37
Some code that could be helpful in using wx.Overlay
Virgil Stokes <vs <at> it.uu.se>
2012-02-08 22:37:44 GMT
2012-02-08 22:37:44 GMT
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
'''
import wx
import sys
print 'Python version: %s\n' %sys.version
print 'wxPython version: %s\n' %wx.version()
TESTMODE = False
TESTMODE = True
class TestPanel(wx.Panel):
# # Define my own subclass for wx.Panel
def __init__(self, parent):
wx.Panel.__init__(self, parent, -1)
# wx.EVT_PAINT will occur when the window (panel) being used for
# drawing must be redrawn (see comments in self.OnPaint for details)
self.Bind(wx.EVT_PAINT, self.onPaint)
# wx.EVT_MOTION will occur when the mouse is moved
self.Bind(wx.EVT_MOTION, self.onMouseMove)
# To save previous cell (rectangle) that mouse was over
self.oldCell = None
# Define the location of two rectangles
self.rect1 = wx.Rect(50,60,200,250)
self.rect2 = wx.Rect(250,60,200,250)
# Create an instance of wx.Overlay (to handle Overlay processing)
self.overlay = wx.Overlay()
if TESTMODE:
self.OnPaintCounter = 0
self.recoverCounter = 0
def onPaint(self, evt):
if TESTMODE:
self.OnPaintCounter += 1
print 'Enter OnPaint -- %3d' %self.OnPaintCounter
## Draw/redraw static objects when wx.EVT_PAINT event fires
# Put some polygons on a sky blue background
dc = wx.PaintDC(self) # create a context for drawing
dc.SetBackground(wx.Brush("sky blue")) # set BG
dc.Clear() # blits BG to screen
dc.SetPen(wx.Pen("red", 1))
dc.SetBrush(wx.CYAN_BRUSH)
coords = ((40,40),(200,220),(210,120),(120,300))
dc.DrawPolygon(coords)
dc.SetPen(wx.Pen("white", 2))
dc.SetBrush(wx.RED_BRUSH)
coords = ((10,50),(100,200),(210,30),(120,280))
dc.DrawPolygon(coords)
# Draw two adjacent cells -- rectangles (only their edges)
dc.SetPen(wx.Pen("black", 2))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangleRect(self.rect1)
dc.SetPen(wx.Pen("green", 2))
dc.DrawRectangleRect(self.rect2)
# The first time wx.DCOverlay is called or after a self.Overlay.Reset(),
# the current screen is mapped to the Overlay. After this
# initialization call it will map the Overlay to the screen.
dc = wx.ClientDC(self)
# Map dc to odc and Overlay -- first execution
odc = wx.DCOverlay(self.overlay, dc)
# Blit bitmap in odc to the screen and clear it in odc
odc.Clear()
def onMouseMove(self, evt):
'''
Purpose: track the movement of the mouse
'''
def recoverBitMap(dc):
'''
Purpose: recover what was placed in the Overlay bitmap
since its last initialization.
[note it's paired with wx.DCOverlay(self.overlay, dc]
'''
if TESTMODE:
self.recoverCounter += 1
print 'Forced recovery of screen -- %3d' %self.recoverCounter
# Map Overlay to odc --- when not the first call
odc = wx.DCOverlay(self.overlay, dc)
# Blit bitmap in odc to the screen and clear it in odc
odc.Clear()
# Note, self.overlay.Reset() clears whatever is in Overlay
# and reinitializes so that the next call to wx.DCOverlay
# will be treated as the first call. See comments in OnPaint.
#self.overlay.Reset()
## Process the position of the mouse wrt cells
cell = None
# Get mouse coordinates (referenced to this frame (panel))
pt = evt.GetPosition()
if self.rect1.Inside(pt):
cell = self.rect1
if self.rect2.Inside(pt):
cell = self.rect2
# Either have not entered a cell yet --- cell = None
# or, in the same cell --- cell = oldCell,
# or, in a new cell
if cell == self.oldCell: return# same cell or have not entered a cell
# New cell has been entered
dc = wx.ClientDC(self)
if self.oldCell:
# Moved from inside another cell
recoverBitMap(dc) # recover orginal (as defined in onPaint)
# Highlight the new cell (edges only) just entered
dc.SetPen(wx.Pen("red", 4))
dc.SetBrush(wx.TRANSPARENT_BRUSH)
dc.DrawRectangleRect(cell)
self.oldCell = cell
class MyApp(wx.App):
# Define my own subclass for wx.App
def OnInit(self):
# The frame (container for the panel) is extremely simple
# and thus a subclass of wx.Frame is not defined
frame = wx.Frame(None, title="wx.Overlay Test", size=(600,450))
# Create my own panel (subclass of frame)
panel = TestPanel(frame)
# Display what is in the frame -- when app.MainLoop() executes
frame.Show(True)
#self.SetTopWindow(frame)
return True
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Every wxPython program must have one application object and one or more
# frame objects!
if __name__ == '__main__':
# Initialize
app = MyApp(False) # the False is important!
# Display frame and start looking for "events" (e.g wx.EVT_PAINT,
# wx.EVT_MOTION)
app.MainLoop()
RSS Feed