Thanks for the interest. I've included the code below. In reply to
your question, no, I'm not doing an event.Skip() on any right click
event. One thing I don't understand is that in Cody Precord's book he
can initiate a right-click event by binding the callback to a
EVT_CONTEXT_MENU event, whereas I have to use a EVT_RIGHT_DOWN since
the former seems to have has no effect in the context of the canvas.
Anyway, here's the code (please bear in mind that this is a first
attempt with wxPython, so be gentle...).
···
On Mar 1, 4:27 pm, werner <wbru...@free.fr> wrote:
On 01/03/2011 13:02, Bob wrote:
> Hi,
> I'm trying to modify the OGL example athttp://wiki.wxpython.org/wxOGL
> such that right clicking on the canvas presents a user with a drop-
> down selection menu, whereas right-clicking on a shape has no such
> effect (I intend using that later). I've tried to cater for these
> requirements by adding the following: First I've added a OnRightClick
> method to the MyEvtHandler class in that example, which works just
> fine if it's the only event handler that deals with right-clicks (it
> only picks right-clicks on shapes). However, when I add an event
> handler to the canvas class via:
> canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnContextMenu)
> where OnContextMenu is a callback which brings up the menu for right-
> clicks on blank areas of the canvas (adapted from example 8, chapter 3
> of Cody Precord's new book), then this handler takes over *all* right
> click events, so right-clicking on a shape no longer fires the correct
> OnRightClick method mentioned above, but this OnContextMenu too. I'm
> guessing that the latter method has overridden the former method.
> So guys, can anyone show me the error of my ways and suggest a
> solution?
You might want to attach your code, should make it easier to spot what
is happening.
Just a guess, are you doing event.Skip()
EventPropagation - wxPyWiki
Werner
######################
#!/usr/bin/env python
import wx
import wx.lib.ogl as ogl
CLICK_TO_DRAG = True
# Menu ID's
ID_RED = wx.NewId()
ID_GREEN = wx.NewId()
ID_BLUE = wx.NewId()
class PopupMenuMixin(object):
def __init__(self, canvas):
super(PopupMenuMixin, self).__init__()
# Attributes
self._menu = None
# Event Handlers
canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnContextMenu)
# canvas.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)
def OnContextMenu(self, event):
"""Creates and shows the Menu"""
if self._menu is not None:
self._menu.Destroy()
self._menu = wx.Menu()
self.CreateContextMenu(self._menu)
self.PopupMenu(self._menu)
def CreateContextMenu(self, menu):
"""Override in subclass to create the menu"""
raise NotImplementedError
class MyApp(wx.App):
def OnInit(self):
ogl.OGLInitialize()
self.frame = MyFrame(None, title="PyDAG")
self.SetTopWindow(self.frame)
self.frame.Show()
return True
class MyEvtHandler(ogl.ShapeEvtHandler):
"""
Overwrite the default event handler to implement some custom
features.
"""
def __init__(self):
ogl.ShapeEvtHandler.__init__(self)
def OnLeftClick(self, x, y, keys = 0, attachment = 0):
"""
The dragging is done here.
"""
shape = self.GetShape()
print shape.__class__, shape.GetClassName(), shape.a
canvas = shape.GetCanvas()
dc = wx.ClientDC(canvas)
canvas.PrepareDC(dc)
if shape.Selected():
shape.Select(False, dc)
canvas.Redraw(dc)
else:
redraw = False
shapeList = canvas.GetDiagram().GetShapeList()
toUnselect =
for s in shapeList:
if s.Selected():
toUnselect.append(s)
shape.Select(True, dc)
if toUnselect:
for s in toUnselect:
s.Select(False, dc)
canvas.Redraw(dc)
def OnRightClick(self, x, y, keys = 0, attachment = 0):
print "OnRightClick activated"
class OGLCanvas(ogl.ShapeCanvas, PopupMenuMixin):
def __init__(self, parent, frame):
ogl.ShapeCanvas.__init__(self, parent)
# Pull in right-click mixin here
PopupMenuMixin.__init__(self, self)
self.Bind(wx.EVT_MENU, self.OnMenu)
self.SetBackgroundColour("LIGHT BLUE")
self.diagram = ogl.Diagram()
self.SetDiagram(self.diagram)
self.diagram.SetCanvas(self)
self.circle = ogl.CircleShape(100)
self.circle.SetCanvas(self)
self.circle.a="Circle identified"
self.diagram.AddShape(self.circle)
self.circle.Show(True)
if CLICK_TO_DRAG:
self.evthandler = MyEvtHandler()
self.evthandler.SetShape(self.circle)
self.evthandler.SetPreviousHandler(self.circle.GetEventHandler())
self.circle.SetEventHandler(self.evthandler)
else:
self.Bind(wx.EVT_MOTION, self.OnMotion, self)
def OnMotion(self, event):
shape = self.circle
bx = shape.GetX()
by = shape.GetY()
bw, bh = shape.GetBoundingBoxMax()
oldrect = wx.Rect(int(bx-bw/2)-1, int(by-bh/2)-1, int(bw)+2,
int(bh)+2)
canvas = shape.GetCanvas()
dc = wx.ClientDC(canvas)
canvas.PrepareDC(dc)
shape.Move(dc, event.GetPosition()[0], event.GetPosition()[1])
canvas.Refresh(False, oldrect)
event.Skip()
def OnMenu(self, event):
"""Handle menu events from the popup menu"""
evt_id = event.GetId()
colour_map = {ID_RED : wx.RED,
ID_GREEN : wx.GREEN,
ID_BLUE : wx.BLUE}
if evt_id in colour_map:
colour = colour_map.get(evt_id)
self.SetBackgroundColour(colour)
self.Refresh()
else:
event.Skip()
def CreateContextMenu(self, menu):
"""Overrides PopupMenuMixin.CreateContextMenu"""
menu.Append(ID_RED, "Red",
"Change background to Red")
menu.Append(ID_GREEN, "Green",
"Change background to Green")
menu.Append(ID_BLUE, "Blue",
"Change background to Blue")
class MyFrame(wx.Frame):
def __init__(self, parent, id=wx.ID_ANY, title="",
pos=wx.DefaultPosition, size=wx.DefaultSize,
style=wx.DEFAULT_FRAME_STYLE,
name="MyFrame"):
super(MyFrame, self).__init__(parent, id, title,
pos, size, style, name)
# Attributes
self.SetBackgroundColour(wx.Colour(8, 197, 248))
# The menu bar
menu_bar = wx.MenuBar()
edit_menu = wx.Menu()
edit_menu.Append(wx.NewId(), "Jobs")
edit_menu.Append(wx.ID_PREFERENCES)
menu_bar.Append(edit_menu, "Edit")
self.SetMenuBar(menu_bar)
self.canvas = OGLCanvas(self, self)
# Layout
self.CreateStatusBar() # To show help text
if __name__ == "__main__":
wx.InitAllImageHandlers()
app = MyApp(False)
app.MainLoop()