wxGlade tutorial - Menu
(Contributed by Chris Lale, chrislale AT users DOT berlios DOT de)
Table of Contents:
Create the application in wxglade
Run wxglade. Open the simple project simple-glade.wxg that you created in "first steps" (WxGladeFirstSteps). The project consists of one empty frame. Set the title to "menu-glade" and save it as menu-glade.wxg. In the main (toolbox) window
Properties - <frame_1> -> Widget -> Title: menu-glade
File -> Save -> /path/to/your/project/menu-glade.wxg
The Tree shows that the application contains one frame (window)and a sizer to added automatically by wxGlade.
Application
frame_1 (MyFrame)
sizer_1
About the wx.Menu class
A menu is a popup (or pull down) list of items, one of which may be selected before the menu goes away (clicking elsewhere dismisses the menu). Menus may be used to construct either menu bars or popup menus.
Look for wxWindow's methods in
wxWidgets manual -> Alphabetical class reference -> wxMenu -> Members
and
wxPython API -> Classes -> Menu -> Methods summary
Construct a menubar object
Look up wx.Menu's __init__() method, or constructor. You should find that __init__() has two string parameters:
- title - A title for the popup menu: the empty string denotes no title.
- style - If set to wxMENU_TEAROFF, the menu will be detachable (wxGTK only).
In the wxGlade Tree window, double-click on frame_1(MyFrame). This opens the Design window and the Properties window for frame_1. The wx.Menu __init__() method is set by the Has MenuBar option in the Widget tab of the Properties window:
Properties - <frame_1> -> Widget -> Has MenuBar: (tick)
This adds these lines to MyFrame's __init()__ method:
The code constructs a new wx.Menu menubar object (frame_1_menubar), and tells the frame to show the menubar with the wx.Frame method SetMenuBar().
Add menu items to the menubar
The menubar is just a container widget - there is nothing to see until you have added some menu items. First, add "File", "Edit" and "Help" items:
Properties - <frame_1_menubar> -> Common -> Edit menus...
This brings up the Menu editor. Add the items and give them labels:
Menu editor -> Add -> Label: &File
Menu editor -> Add -> Label: &Edit
Menu editor -> Add -> Label: &Help
Menu editor -> OK
Check the result:
Properties - <frame_1> -> Common -> Preview
Add menu items to the File menu
Now add some items to the File menu:
Properties - <frame_1_menubar> -> Common -> Edit menus...
Menu editor -> Add -> Label: &Open
Use the "Down" button to move the item directly below "&File". Use the ">" button to demote the item one level. In the same way, add items for "&Save" and "&Quit:
Menu editor -> Add -> Label: &Save
Menu editor -> Add -> Label: &Quit
Now highlight "&Save" and insert a separator above "&Quit"
Menu editor -> Add separator
Menu editor -> OK
Check the result:
Properties - <frame_1> -> Common -> Preview
Generate the Python code. In the Tree window, select Application.
In the Properties window, enter a new filename for the python file.
Output path: /path/to/your/project/simple2-glade.py
Click on
Generate code
Look at the code in a text editor or Idle:
1 # Menu Bar
2 self.frame_1_menubar = wx.MenuBar()
3 self.SetMenuBar(self.frame_1_menubar)
4 wxglade_tmp_menu = wx.Menu()
5 wxglade_tmp_menu.Append(wx.NewId(), "&Open", "", wx.ITEM_NORMAL)
6 wxglade_tmp_menu.Append(wx.NewId(), "&Save", "", wx.ITEM_NORMAL)
7 wxglade_tmp_menu.AppendSeparator()
8 wxglade_tmp_menu.Append(wx.NewId(), "&Quit", "", wx.ITEM_NORMAL)
9 self.frame_1_menubar.Append(wxglade_tmp_menu, "&File")
10 wxglade_tmp_menu = wx.Menu()
11 self.frame_1_menubar.Append(wxglade_tmp_menu, "&Edit")
12 wxglade_tmp_menu = wx.Menu()
13 self.frame_1_menubar.Append(wxglade_tmp_menu, "&Help")
14 # Menu Bar end
Add a keyboard accelerator to the Quit menu item
The item string for the normal menu items (not submenus or separators) may include the accelerator which can be used to activate the menu item from keyboard. The accelerator string follows the item label and is separated from it by a TAB character ('\t'). Its general syntax is any combination of "CTRL", "ALT" and "SHIFT" strings (case doesn't matter) separated by either '-' or '+' characters and followed by the accelerator key itself.
Use the menu editor to add the key combination ctrl-q to the Quit menu item:
Menu editor -> Add -> Label: &Quit\tCtrl+Q
Make the Quit menu item close the application
Use wxGlade to create an event handler that reponds to "Quit" being selected. In wxGlade, edit the entry for "&Quit" and add an event handler called OnQuit:
Properties - <frame_1_menubar> -> Common -> Edit menus...
Menu editor -> &Quit\tCtrl+Q -> Event Handler: OnQuit
Generate the Python code. Look at the code in a text editor or Idle. wxGlade has added a new OnQuit method to the MyFrame class:
Also, a new method is added to MyFrame's __init__() method to bind the "Quit" menu item to the OnQuit() method:
1 self.Bind(wx.EVT_MENU, self.OnQuit, self.quit)
If you run menu-glade.py from a terminal window and click on
File -> Quit
"Event handler OnQuit not implemented" is printed to standard output (the terminal window).Replace
1 print "Event handler `OnQuit` not implemented"
with
1 self.Close()
Save the file and run it. Now, clicking on
File -> Quit
invokes the Close() method which is inherited by MyFrame from wx.Window.
Add an icon to the Quit item
Make sure that stock_quit.png exists in the working directory. In Linux systems with Gtk, you can find it somewhere like /usr/share/icons/hicolor/16x16/stock/generic/stock_exit.png.
You must add the SetBitmap() method to the code manually. To do this, you must first create the "File" menu as a named wx.Menu object, and the "Quit" menu item as a named wx.MenuItem object.
In wxGlade, edit the entry for "&File" and add the Name file:
Properties - <frame_1_menubar> -> Common -> Edit menus...
Menu editor -> &File -> Name: file
Do the same for "&quit":
Menu editor -> &Quit -> Name: quit
Generate the Python code. Look at the code in a text editor or Idle:
1 # Menu Bar
2 self.frame_1_menubar = wx.MenuBar()
3 self.SetMenuBar(self.frame_1_menubar)
4 self.file = wx.Menu()
5 self.file.Append(wx.NewId(), "&Open", "", wx.ITEM_NORMAL)
6 self.file.Append(wx.NewId(), "&Save", "", wx.ITEM_NORMAL)
7 self.file.AppendSeparator()
8 self.quit = wx.MenuItem(self.file, wx.NewId(), "&Quit\tCtrl+Q", "", wx.ITEM_NORMAL)
9 self.file.AppendItem(self.quit)
10 self.frame_1_menubar.Append(self.file, "&File")
11 wxglade_tmp_menu = wx.Menu()
12 self.frame_1_menubar.Append(wxglade_tmp_menu, "&Edit")
13 wxglade_tmp_menu = wx.Menu()
14 self.frame_1_menubar.Append(wxglade_tmp_menu, "&Help")
15 # Menu Bar end
Notice how
has become
and
1 wxglade_tmp_menu.Append(wx.NewId(), "&Quit\tCtrl+Q", "", wx.ITEM_NORMAL)
has become
Now add the stock_exit.png image using the SetBitMap() method. wxPython can only put bitmaps into menus. You must convert the .png file to a bitmap using ConvertToBitmap(). Insert this line just after the line that creates the "quit" menuitem object:
The Menu Bar section now looks like this.
1 # Menu Bar
2 self.frame_1_menubar = wx.MenuBar()
3 self.SetMenuBar(self.frame_1_menubar)
4 self.file = wx.Menu()
5 self.file.Append(wx.NewId(), "&Open", "", wx.ITEM_NORMAL)
6 self.file.Append(wx.NewId(), "&Save", "", wx.ITEM_NORMAL)
7 self.file.AppendSeparator()
8 self.quit = wx.MenuItem(self.file, wx.NewId(), "&Quit\tCtrl+Q", "", wx.ITEM_NORMAL)
9 self.quit.SetBitmap(wx.Image('stock_exit.png',
10 wx.BITMAP_TYPE_PNG).ConvertToBitmap())
11 self.file.AppendItem(self.quit)
12 self.frame_1_menubar.Append(self.file, "&File")
13 wxglade_tmp_menu = wx.Menu()
14 self.frame_1_menubar.Append(wxglade_tmp_menu, "&Edit")
15 wxglade_tmp_menu = wx.Menu()
16 self.frame_1_menubar.Append(wxglade_tmp_menu, "&Help")
17 # Menu Bar end
Save menu-glade.py and run it. Check that you can see the icon in the "Quit" menu item.
You may find that the SetBitmap() line is deleted next time you regenerate menu-glade.py from wxGlade. For this reason, add icons to menus only after you have finished building the complete GUI.
Comment... Or write your manual statements after the end-comment. Only lines within # XXX and # XXX end are replaced.
Appendix: The complete code
1 #!/usr/bin/env python
2 # -*- coding: ISO-8859-1 -*-
3 # generated by wxGlade 0.4.1 on Tue Mar 28 19:05:38 2006
4
5 import wx
6
7 class MyFrame(wx.Frame):
8 def __init__(self, *args, **kwds):
9 # begin wxGlade: MyFrame.__init__
10 kwds["style"] = wx.DEFAULT_FRAME_STYLE
11 wx.Frame.__init__(self, *args, **kwds)
12
13 # Menu Bar
14 self.frame_1_menubar = wx.MenuBar()
15 self.SetMenuBar(self.frame_1_menubar)
16 self.file = wx.Menu()
17 self.file.Append(wx.NewId(), "&Open", "", wx.ITEM_NORMAL)
18 self.file.Append(wx.NewId(), "&Save", "", wx.ITEM_NORMAL)
19 self.file.AppendSeparator()
20 self.quit = wx.MenuItem(self.file, wx.NewId(), "&Quit\tCtrl+Q", "", wx.ITEM_NORMAL)
21 self.quit.SetBitmap(wx.Image('stock_exit.png',
22 wx.BITMAP_TYPE_PNG).ConvertToBitmap())
23 self.file.AppendItem(self.quit)
24 self.frame_1_menubar.Append(self.file, "&File")
25 wxglade_tmp_menu = wx.Menu()
26 self.frame_1_menubar.Append(wxglade_tmp_menu, "&Edit")
27 wxglade_tmp_menu = wx.Menu()
28 self.frame_1_menubar.Append(wxglade_tmp_menu, "&Help")
29 # Menu Bar end
30
31 self.__set_properties()
32 self.__do_layout()
33
34 self.Bind(wx.EVT_MENU, self.OnQuit, self.quit)
35 # end wxGlade
36
37 def __set_properties(self):
38 # begin wxGlade: MyFrame.__set_properties
39 self.SetTitle("menu-glade")
40 self.SetSize((343, 510))
41 # end wxGlade
42
43 def __do_layout(self):
44 # begin wxGlade: MyFrame.__do_layout
45 sizer_1 = wx.BoxSizer(wx.VERTICAL)
46 self.SetAutoLayout(True)
47 self.SetSizer(sizer_1)
48 self.Layout()
49 # end wxGlade
50
51 def OnQuit(self, event): # wxGlade: MyFrame.<event_handler>
52 self.Close()
53 event.Skip()
54
55 # end of class MyFrame
56
57
58 class MyApp(wx.App):
59 def OnInit(self):
60 wx.InitAllImageHandlers()
61 frame_1 = MyFrame(None, -1, "")
62 self.SetTopWindow(frame_1)
63 frame_1.Show()
64 return 1
65
66 # end of class MyApp
67
68 if __name__ == "__main__":
69 app = MyApp(0)
70 app.MainLoop()