== Introduction == The following code was committed by Chris Barker on the wxPython-users mailing list. Popup menu is here implemented in a separate class. This way, you don't have to manually check, if the events were already bound. == What Objects are Involved == {{{wxSimpleApp}}} - this class serves as a entry point to the application {{{wxMenu}}} - used for implementing the Popup Menu {{{wxMenuItem}}} - all items from Popup Menu are created with this class {{{wxWindow}}} - we create four different windows in one Frame {{{wxFrame}}} - a toplevel window and a container for our four windows == Process Overview == The example implements a Popup Menu in a single frame. This frame is divided into four windows. If you right click on a Frame, a context menu pops up. Context menu consists of three commands. If you select any of them, a message is sent to the console. It will say the item you selected plus the color of the window where you clicked with the mouse. This example shows the power of the object oriented programming. Imagine you would have to do it the other way, by calculating manually the position of the pointer! (to find out the colour) Application just knows it... Notice that the popup menu is implemented as a new class. There is one subtle thing in the code that needs some clarification. You only bound an event to a method once. It resides in event table afterwards. If it is done in the constructor, everything is ok. But when you bound an event in a method, you do it every time the method gets invoked. That's why there needs to be a condition in the beginning of the method. To ensure binding is done only once. Taken from the Demo: {{{ if not hasattr(self, "popupID1"): self.popupID1 = wx.NewId() self.popupID2 = wx.NewId() self.Bind(wx.EVT_MENU, self.OnPopupOne, id=self.popupID1) self.Bind(wx.EVT_MENU, self.OnPopupTwo, id=self.popupID2) }}} Thus, with a Popup Menu implemented in a special class, you get a more elegant code. == Code Sample == {{{#!python #!/usr/bin/python import wx app = wx.PySimpleApp() class MyPopupMenu(wx.Menu): def __init__(self, WinName): wx.Menu.__init__(self) self.WinName = WinName item = wx.MenuItem(self, wx.NewId(), "Item One") self.AppendItem(item) self.Bind(wx.EVT_MENU, self.OnItem1, item) item = wx.MenuItem(self, wx.NewId(),"Item Two") self.AppendItem(item) self.Bind(wx.EVT_MENU, self.OnItem2, item) item = wx.MenuItem(self, wx.NewId(),"Item Three") self.AppendItem(item) self.Bind(wx.EVT_MENU, self.OnItem3, item) def OnItem1(self, event): print "Item One selected in the %s window"%self.WinName def OnItem2(self, event): print "Item Two selected in the %s window"%self.WinName def OnItem3(self, event): print "Item Three selected in the %s window"%self.WinName class MyWindow(wx.Window): def __init__(self, parent, color): wx.Window.__init__(self, parent, -1) self.color = color self.SetBackgroundColour(color) self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown) def OnRightDown(self,event): menu = MyPopupMenu(self.color) self.PopupMenu(menu, event.GetPosition()) menu.Destroy() class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self,None, -1, "Test", size=(300, 200)) sizer = wx.GridSizer(2,2,5,5) sizer.Add(MyWindow(self,"blue"),1,wx.GROW) sizer.Add(MyWindow(self,"yellow"),1,wx.GROW) sizer.Add(MyWindow(self,"red"),1,wx.GROW) sizer.Add(MyWindow(self,"green"),1,wx.GROW) self.SetSizer(sizer) self.Show() frame = MyFrame() app.SetTopWindow(frame) app.MainLoop() }}}