| 1 | #------------------------------------------------------------------- |
| 2 | # essaimenu.py |
| 3 | # |
| 4 | # menus in wxPython 2.3.3 |
| 5 | # |
| 6 | #------------------------------------------------------------------- |
| 7 | # |
| 8 | # o Debug message when adding a menu item (see last menu): |
| 9 | # |
| 10 | # Debug: ..\..\src\msw\menuitem.cpp(370): 'GetMenuState' failed with |
| 11 | # error 0x00000002 (the system cannot find the file specified.). |
| 12 | # |
| 13 | |
| 14 | import time |
| 15 | import wx |
| 16 | import images |
| 17 | |
| 18 | #------------------------------------------------------------------- |
| 19 | |
| 20 | class MyFrame(wx.Frame): |
| 21 | |
| 22 | def __init__(self, parent, id, log): |
| 23 | wx.Frame.__init__(self, parent, id, 'Playing with menus', size=(400, 200)) |
| 24 | self.log = log |
| 25 | self.CenterOnScreen() |
| 26 | |
| 27 | self.CreateStatusBar() |
| 28 | self.SetStatusText("This is the statusbar") |
| 29 | |
| 30 | tc = wx.TextCtrl(self, -1, """ |
| 31 | A bunch of bogus menus have been created for this frame. You |
| 32 | can play around with them to see how they behave and then |
| 33 | check the source for this sample to see how to implement them. |
| 34 | """, style=wx.TE_READONLY|wx.TE_MULTILINE) |
| 35 | |
| 36 | # Prepare the menu bar |
| 37 | menuBar = wx.MenuBar() |
| 38 | |
| 39 | # 1st menu from left |
| 40 | menu1 = wx.Menu() |
| 41 | menu1.Append(101, "&Mercury", "This the text in the Statusbar") |
| 42 | menu1.Append(102, "&Venus", "") |
| 43 | menu1.Append(103, "&Earth", "You may select Earth too") |
| 44 | menu1.AppendSeparator() |
| 45 | menu1.Append(104, "&Close", "Close this frame") |
| 46 | # Add menu to the menu bar |
| 47 | menuBar.Append(menu1, "&Planets") |
| 48 | |
| 49 | # 2nd menu from left |
| 50 | menu2 = wx.Menu() |
| 51 | menu2.Append(201, "Hydrogen") |
| 52 | menu2.Append(202, "Helium") |
| 53 | # a submenu in the 2nd menu |
| 54 | submenu = wx.Menu() |
| 55 | submenu.Append(2031,"Lanthanium") |
| 56 | submenu.Append(2032,"Cerium") |
| 57 | submenu.Append(2033,"Praseodymium") |
| 58 | menu2.AppendMenu(203, "Lanthanides", submenu) |
| 59 | # Append 2nd menu |
| 60 | menuBar.Append(menu2, "&Elements") |
| 61 | |
| 62 | menu3 = wx.Menu() |
| 63 | # Radio items |
| 64 | menu3.Append(301, "IDLE", "a Python shell using tcl/tk as GUI", wx.ITEM_RADIO) |
| 65 | menu3.Append(302, "PyCrust", "a Python shell using wxPython as GUI", wx.ITEM_RADIO) |
| 66 | menu3.Append(303, "psi", "a simple Python shell using wxPython as GUI", wx.ITEM_RADIO) |
| 67 | menu3.AppendSeparator() |
| 68 | menu3.Append(304, "project1", "", wx.ITEM_NORMAL) |
| 69 | menu3.Append(305, "project2", "", wx.ITEM_NORMAL) |
| 70 | menuBar.Append(menu3, "&Shells") |
| 71 | |
| 72 | menu4 = wx.Menu() |
| 73 | # Check menu items |
| 74 | menu4.Append(401, "letters", "abcde...", wx.ITEM_CHECK) |
| 75 | menu4.Append(402, "digits", "123...", wx.ITEM_CHECK) |
| 76 | menu4.Append(403, "letters and digits", "abcd... + 123...", wx.ITEM_CHECK) |
| 77 | menuBar.Append(menu4, "Chec&k") |
| 78 | |
| 79 | menu5 = wx.Menu() |
| 80 | # Show how to put an icon in the menu |
| 81 | item = wx.MenuItem(menu5, 500, "&Smile!\tCtrl+S", "This one has an icon") |
| 82 | item.SetBitmap(images.getSmilesBitmap()) |
| 83 | menu5.AppendItem(item) |
| 84 | |
| 85 | # Shortcuts |
| 86 | menu5.Append(501, "Interesting thing\tCtrl+A", "Note the shortcut!") |
| 87 | menu5.AppendSeparator() |
| 88 | menu5.Append(502, "Hello\tShift+H") |
| 89 | menu5.AppendSeparator() |
| 90 | menu5.Append(503, "remove the submenu") |
| 91 | menu6 = wx.Menu() |
| 92 | menu6.Append(601, "Submenu Item") |
| 93 | menu5.AppendMenu(504, "submenu", menu6) |
| 94 | menu5.Append(505, "remove this menu") |
| 95 | menu5.Append(506, "this is updated") |
| 96 | menu5.Append(507, "insert after this...") |
| 97 | menu5.Append(508, "...and before this") |
| 98 | menuBar.Append(menu5, "&Fun") |
| 99 | |
| 100 | self.SetMenuBar(menuBar) |
| 101 | |
| 102 | # Menu events |
| 103 | self.Bind(wx.EVT_MENU_HIGHLIGHT_ALL, self.OnMenuHighlight) |
| 104 | |
| 105 | self.Bind(wx.EVT_MENU, self.Menu101, id=101) |
| 106 | self.Bind(wx.EVT_MENU, self.Menu102, id=102) |
| 107 | self.Bind(wx.EVT_MENU, self.Menu103, id=103) |
| 108 | self.Bind(wx.EVT_MENU, self.CloseWindow, id=104) |
| 109 | |
| 110 | self.Bind(wx.EVT_MENU, self.Menu201, id=201) |
| 111 | self.Bind(wx.EVT_MENU, self.Menu202, id=202) |
| 112 | self.Bind(wx.EVT_MENU, self.Menu2031, id=2031) |
| 113 | self.Bind(wx.EVT_MENU, self.Menu2032, id=2032) |
| 114 | self.Bind(wx.EVT_MENU, self.Menu2033, id=2033) |
| 115 | |
| 116 | self.Bind(wx.EVT_MENU, self.Menu301To303, id=301) |
| 117 | self.Bind(wx.EVT_MENU, self.Menu301To303, id=302) |
| 118 | self.Bind(wx.EVT_MENU, self.Menu301To303, id=303) |
| 119 | self.Bind(wx.EVT_MENU, self.Menu304, id=304) |
| 120 | self.Bind(wx.EVT_MENU, self.Menu305, id=305) |
| 121 | |
| 122 | # Range of menu items |
| 123 | self.Bind(wx.EVT_MENU_RANGE, self.Menu401To403, id=401, id2=403) |
| 124 | |
| 125 | self.Bind(wx.EVT_MENU, self.Menu500, id=500) |
| 126 | self.Bind(wx.EVT_MENU, self.Menu501, id=501) |
| 127 | self.Bind(wx.EVT_MENU, self.Menu502, id=502) |
| 128 | self.Bind(wx.EVT_MENU, self.TestRemove, id=503) |
| 129 | self.Bind(wx.EVT_MENU, self.TestRemove2, id=505) |
| 130 | self.Bind(wx.EVT_MENU, self.TestInsert, id=507) |
| 131 | self.Bind(wx.EVT_MENU, self.TestInsert, id=508) |
| 132 | |
| 133 | wx.GetApp().Bind(wx.EVT_UPDATE_UI, self.TestUpdateUI, id=506) |
| 134 | |
| 135 | # Methods |
| 136 | |
| 137 | def OnMenuHighlight(self, event): |
| 138 | # Show how to get menu item info from this event handler |
| 139 | id = event.GetMenuId() |
| 140 | item = self.GetMenuBar().FindItemById(id) |
| 141 | if item: |
| 142 | text = item.GetText() |
| 143 | help = item.GetHelp() |
| 144 | |
| 145 | # but in this case just call Skip so the default is done |
| 146 | event.Skip() |
| 147 | |
| 148 | |
| 149 | def Menu101(self, event): |
| 150 | self.log.write('Welcome to Mercury\n') |
| 151 | |
| 152 | def Menu102(self, event): |
| 153 | self.log.write('Welcome to Venus\n') |
| 154 | |
| 155 | def Menu103(self, event): |
| 156 | self.log.write('Welcome to the Earth\n') |
| 157 | |
| 158 | def CloseWindow(self, event): |
| 159 | self.Close() |
| 160 | |
| 161 | def Menu201(self, event): |
| 162 | self.log.write('Chemical element number 1\n') |
| 163 | |
| 164 | def Menu202(self, event): |
| 165 | self.log.write('Chemical element number 2\n') |
| 166 | |
| 167 | def Menu2031(self, event): |
| 168 | self.log.write('Element number 57\n') |
| 169 | |
| 170 | def Menu2032(self, event): |
| 171 | self.log.write('Element number 58\n') |
| 172 | |
| 173 | def Menu2033(self, event): |
| 174 | self.log.write('Element number 59\n') |
| 175 | |
| 176 | def Menu301To303(self, event): |
| 177 | id = event.GetId() |
| 178 | self.log.write('Event id: %d\n' % id) |
| 179 | |
| 180 | def Menu304(self, event): |
| 181 | self.log.write('Not yet available\n') |
| 182 | |
| 183 | def Menu305(self, event): |
| 184 | self.log.write('Still vapour\n') |
| 185 | |
| 186 | def Menu401To403(self, event): |
| 187 | self.log.write('From a EVT_MENU_RANGE event\n') |
| 188 | |
| 189 | def Menu500(self, event): |
| 190 | self.log.write('Have a happy day!\n') |
| 191 | |
| 192 | def Menu501(self, event): |
| 193 | self.log.write('Look in the code how the shortcut has been realized\n') |
| 194 | |
| 195 | def Menu502(self, event): |
| 196 | self.log.write('Hello from Jean-Michel\n') |
| 197 | |
| 198 | |
| 199 | def TestRemove(self, evt): |
| 200 | mb = self.GetMenuBar() |
| 201 | submenuItem = mb.FindItemById(601) |
| 202 | |
| 203 | if not submenuItem: |
| 204 | return |
| 205 | |
| 206 | submenu = submenuItem.GetMenu() |
| 207 | menu = submenu.GetParent() |
| 208 | |
| 209 | # This works |
| 210 | #menu.Remove(504) |
| 211 | |
| 212 | # this also works |
| 213 | menu.RemoveItem(mb.FindItemById(504)) |
| 214 | |
| 215 | # This doesn't work, as expected since submenuItem is not on menu |
| 216 | #menu.RemoveItem(submenuItem) |
| 217 | |
| 218 | |
| 219 | def TestRemove2(self, evt): |
| 220 | mb = self.GetMenuBar() |
| 221 | mb.Remove(4) |
| 222 | |
| 223 | |
| 224 | def TestUpdateUI(self, evt): |
| 225 | text = time.ctime() |
| 226 | evt.SetText(text) |
| 227 | |
| 228 | |
| 229 | def TestInsert(self, evt): |
| 230 | theID = 508 |
| 231 | # get the menu |
| 232 | mb = self.GetMenuBar() |
| 233 | menuItem = mb.FindItemById(theID) |
| 234 | menu = menuItem.GetMenu() |
| 235 | |
| 236 | # figure out the position to insert at |
| 237 | pos = 0 |
| 238 | |
| 239 | for i in menu.GetMenuItems(): |
| 240 | if i.GetId() == theID: |
| 241 | break |
| 242 | |
| 243 | pos += 1 |
| 244 | |
| 245 | # now insert the new item |
| 246 | ID = wx.NewId() |
| 247 | ##menu.Insert(pos, ID, "NewItem " + str(ID)) |
| 248 | item = wx.MenuItem(menu) |
| 249 | item.SetId(ID) |
| 250 | item.SetText("NewItem " + str(ID)) |
| 251 | menu.InsertItem(pos, item) |
| 252 | |
| 253 | |
| 254 | #--------------------------------------------------------------------------- |
| 255 | |
| 256 | class TestPanel(wx.Panel): |
| 257 | def __init__(self, parent, log): |
| 258 | self.log = log |
| 259 | wx.Panel.__init__(self, parent, -1) |
| 260 | |
| 261 | b = wx.Button(self, -1, "Show the Menu sample", (50,50)) |
| 262 | self.Bind(wx.EVT_BUTTON, self.OnButton, b) |
| 263 | |
| 264 | |
| 265 | def OnButton(self, evt): |
| 266 | win = MyFrame(self, -1, self.log) |
| 267 | win.Show(True) |
| 268 | |
| 269 | |
| 270 | #--------------------------------------------------------------------------- |
| 271 | |
| 272 | |
| 273 | def runTest(frame, nb, log): |
| 274 | win = TestPanel(nb, log) |
| 275 | return win |
| 276 | |
| 277 | #------------------------------------------------------------------- |
| 278 | |
| 279 | |
| 280 | overview = """\ |
| 281 | A demo of using wx.MenuBar and wx.Menu in various ways. |
| 282 | |
| 283 | A menu is a popup (or pull down) list of items, one of which may be selected |
| 284 | before the menu goes away (clicking elsewhere dismisses the menu). Menus may be |
| 285 | used to construct either menu bars or popup menus. |
| 286 | |
| 287 | A menu item has an integer ID associated with it which can be used to identify |
| 288 | the selection, or to change the menu item in some way. A menu item with a special |
| 289 | identifier -1 is a separator item and doesn't have an associated command but just |
| 290 | makes a separator line appear in the menu. |
| 291 | |
| 292 | Menu items may be either normal items, check items or radio items. Normal items |
| 293 | don't have any special properties while the check items have a boolean flag associated |
| 294 | to them and they show a checkmark in the menu when the flag is set. wxWindows |
| 295 | automatically toggles the flag value when the item is clicked and its value may |
| 296 | be retrieved using either IsChecked method of wx.Menu or wx.MenuBar itself or by |
| 297 | using wxEvent.IsChecked when you get the menu notification for the item in question. |
| 298 | |
| 299 | The radio items are similar to the check items except that all the other items |
| 300 | in the same radio group are unchecked when a radio item is checked. The radio group |
| 301 | is formed by a contiguous range of radio items, i.e. it starts at the first item of |
| 302 | this kind and ends with the first item of a different kind (or the end of the menu). |
| 303 | Notice that because the radio groups are defined in terms of the item positions |
| 304 | inserting or removing the items in the menu containing the radio items risks to not |
| 305 | work correctly. Finally note that the radio items are only supported under Windows |
| 306 | and GTK+ currently. |
| 307 | |
| 308 | """ |
| 309 | |
| 310 | |
| 311 | if __name__ == '__main__': |
| 312 | import sys,os |
| 313 | import run |
| 314 | run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) |
| 315 | |