Introduction

Make a popup menu when you right-click something.

What Objects are Involved

Source Component

Component that was clicked.

{1} Menu Launcher

Event handler, launches the menu.

{2} Menu

Popup menu itself.

{3} Menu Handlers

Menu responses to selection.

Process Overview

  1. Register source's EVT_s to invoke {1} launcher.

  2. {1} Launcher creates {2} wxMenu.

  3. {1} Launcher packs {2} menu with Append.

  4. {1} Launcher registers {3} menu handlers with EVT_MENU, on the {2} menu.

  5. {1} Launcher displays {2} menu with call to PopupMenu, invoked on the source component, passing event's GetPoint.

The GetPoint tells PopupMenu where to place the PopupMenu. (That is: Where the user right-clicked, the popup menu should appear.)

Special Concerns

In general:

The code below:

Code Sample

   1 from wxPython.wx import *
   2 
   3 
   4 
   5 menu_titles = [ "Open",
   6                 "Properties",
   7                 "Rename",
   8                 "Delete" ]
   9 
  10 menu_title_by_id = {}
  11 for title in menu_titles:
  12     menu_title_by_id[ wxNewId() ] = title
  13 
  14 
  15 
  16 list_title = "files"
  17 list_items = [ "binding.py",
  18                "clipboard.py",
  19                "config.py",
  20                "debug.py",
  21                "dialog.py",
  22                "dispatch.py",
  23                "error.py", ]
  24 
  25 
  26 
  27 class App( wxPySimpleApp ):
  28     def OnInit( self ):
  29         # build frame
  30         frame = wxFrame(NULL, -1, "Hello from wxPython")
  31         self.frame = frame # we'll use in RightClickCb
  32 
  33         # build list
  34         list  = wxListCtrl( frame, -1, style=wxLC_REPORT )
  35         list.InsertColumn( 0, list_title )
  36         for x in list_items: list.InsertStringItem(0,x)
  37 
  38         ### 1. Register source's EVT_s to invoke launcher. ###
  39         EVT_LIST_ITEM_RIGHT_CLICK( list, -1, self.RightClickCb )
  40 
  41         # clear variables
  42         self.list_item_clicked = None
  43 
  44         # show & run
  45         frame.Show(1)
  46         return 1
  47 
  48     def RightClickCb( self, event ):
  49         # record what was clicked
  50         self.list_item_clicked = right_click_context = event.GetText()
  51         
  52         ### 2. Launcher creates wxMenu. ###
  53         menu = wxMenu()
  54         for (id,title) in menu_title_by_id.items():
  55             ### 3. Launcher packs menu with Append. ###
  56             menu.Append( id, title )
  57             ### 4. Launcher registers menu handlers with EVT_MENU, on the menu. ###
  58             EVT_MENU( menu, id, self.MenuSelectionCb )
  59 
  60         ### 5. Launcher displays menu with call to PopupMenu, invoked on the source component, passing event's GetPoint. ###
  61         self.frame.PopupMenu( menu, event.GetPoint() )
  62         menu.Destroy() # destroy to avoid mem leak
  63         
  64     def MenuSelectionCb( self, event ):
  65         # do something
  66         operation = menu_title_by_id[ event.GetId() ]
  67         target    = self.list_item_clicked
  68         print 'Perform "%(operation)s" on "%(target)s."' % vars()
  69 
  70 app = App()
  71 app.MainLoop()

Comments

Commit code improvements above, comment freely below. -- LionKimbro 2003-08-21 14:40:27

Experiment with the icons {1} {2} {3}. Ideally, I'd get around to installing working Java on Mozilla, and then I could just diagram this process exactly like I want to... -- LionKimbro 2003-10-17 11:59:29

The above code has some problem in wx 2.5.3.1, in right click callback a call to event.GetText() returns empty string. Same for 2.6.0.0, so I think it's some "backward incompatibility" with wx... ;). -- Jarek Zgoda

wx.Menu objects need to be explicitly destroyed (e.g. menu.Destroy()) in this situation. Otherwise, they will rack up the USER Objects count on Windows; eventually crashing a program when USER Objects is maxed out. -- U. Artie Eoff 2008-10-06 12:02:00

PopupMenuOnRightClick (last edited 2008-10-06 18:02:53 by customer-66-213-128-138)

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