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

   1 #!/usr/bin/python
   3 import wx
   5 app = wx.PySimpleApp()
   7 class MyPopupMenu(wx.Menu):
   8     def __init__(self, WinName):
   9         wx.Menu.__init__(self)
  11         self.WinName = WinName
  13         item = wx.MenuItem(self, wx.NewId(), "Item One")
  14         self.AppendItem(item)
  15         self.Bind(wx.EVT_MENU, self.OnItem1, item)
  17         item = wx.MenuItem(self, wx.NewId(),"Item Two")
  18         self.AppendItem(item)
  19         self.Bind(wx.EVT_MENU, self.OnItem2, item)
  21         item = wx.MenuItem(self, wx.NewId(),"Item Three")
  22         self.AppendItem(item)
  23         self.Bind(wx.EVT_MENU, self.OnItem3, item)
  25     def OnItem1(self, event):
  26         print "Item One selected in the %s window"%self.WinName
  28     def OnItem2(self, event):
  29         print "Item Two selected in the %s window"%self.WinName
  31     def OnItem3(self, event):
  32         print "Item Three selected in the %s window"%self.WinName
  34 class MyWindow(wx.Window):
  35     def __init__(self, parent, color):
  36         wx.Window.__init__(self, parent, -1)
  38         self.color = color
  40         self.SetBackgroundColour(color)
  41         self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
  43     def OnRightDown(self,event):
  44         menu = MyPopupMenu(self.color)
  45         self.PopupMenu(menu, event.GetPosition())
  46         menu.Destroy()
  48 class MyFrame(wx.Frame):
  49     def __init__(self):
  50         wx.Frame.__init__(self,None, -1, "Test", size=(300, 200))
  52         sizer = wx.GridSizer(2,2,5,5)
  54         sizer.Add(MyWindow(self,"blue"),1,wx.GROW)
  55         sizer.Add(MyWindow(self,"yellow"),1,wx.GROW)
  56         sizer.Add(MyWindow(self,"red"),1,wx.GROW)
  57         sizer.Add(MyWindow(self,"green"),1,wx.GROW)
  59         self.SetSizer(sizer)
  61         self.Show()
  64 frame = MyFrame()
  65 app.SetTopWindow(frame)
  66 app.MainLoop()

PopupMenuRevised (last edited 2008-07-13 19:04:52 by 69-30-77-125)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.