Table of Contents
Quite a few new widgets and support objects were added in PyGTK 2.4 including:
Action,
RadioAction, ToggleAction -
objects that represent actions that a user can take. Actions contain
information to be used to create proxy widgets ( for example, icons, menu
items and toolbar items).ActionGroup - an object containing
Actions that have some relationship, for example, actions to open, close and
print a document.Border - an object containing the
values for a border.ColorButton - a button used to
launch a ColorSelectionDialog.ComboBox - a widget providing a list
of items to choose from. It replaces the
OptionMenu.ComboBoxEntry - a widget providing a
text entry field with a dropdown list of items to choose from. It replaces
the Combo.EntryCompletion - an object
providing completion for an Entry widget.Expander - a container that can show
and hide its child in response to its button click.FileChooser - an interface for
choosing files.FileChooserWidget - a widget
implementing the FileChooser interface. It replaces
the FileSelection widget.FileChooserDialog - a dialog used
for "File/Open" and "File/Save" actions. It replaces the
FileSelectionDialog.FileFilter - an object used to
filter files based on an internal set of rules.FontButton - a button that launches
the FontSelectionDialog.IconInfo - an object containing
information about an icon in an IconTheme.IconTheme - an object providing
lookup of icons by name and size.ToolItem,
ToolButton, RadioToolButton,
SeparatorToolItem,
ToggleToolButton - widgets that can be added to a
Toolbar. These replace the previous
Toolbar items.TreeModelFilter - an object providing
a powerful mechanism for revising the representation of an underlying
TreeModel. This is described in Section 14.10.2, “TreeModelFilter”.UIManager - an object providing a
way to construct menus and toolbars from an XML UI description. It also has
methods to manage the merging and separation of multiple UI
descriptions.The Action and
ActionGroup objects work together to provide the
images, text, callbacks and accelerators for your application menus and
toolbars. The UIManager uses
Actions and ActionGroups to
build the menubars and toolbars automatically based on a XML
specification. It's much easier to create and populate menus and toolbars
using the UIManager described in a later section. The
following sections on the Action and
ActionGroup objects describe how to directly apply
these objects but I recommend using the UIManager
whenever possible.
An Action object represents an action that
the user can take using an application user interface. It contains
information used by proxy UI elements (for example,
MenuItems or Toolbar items) to
present the action to the user. There are two subclasses of
Action:
ToggleAction | An Action that can be toggled
between two states. |
RadioAction | An Action that can be grouped so
that only one can be active. |
For example, the standard → menu item can be represented
with an icon, mnemonic text and accelerator. When activated, the menu item
triggers a callback that could exit the application. Likewise a
Toolbar button could
share the icon, mnemonic text and callback. Both of these UI elements could
be proxies of the same Action.
Ordinary Button,
ToggleButton and RadioButton
widgets can also act as proxies for an Action though
there is no support for these in the
UIManager.
An Action can be created using the
constructor:
action = gtk.Action(name,label,tooltip,stock_id)
name is a string used to identify the
Action in an ActionGroup or in
a UIManager
specification. label and
tooltip are strings used as the label and tooltip in
proxy widgets. If label is None
then the stock_id must be a string specifying a Stock
Item to get the label from. If tooltip is
None the Action will not have a
tooltip.
As we'll see in Section 16.1.2, “ActionGroups” it's
much easier to create Action objects using the
ActionGroup convenience methods:
actiongroup.add_actions(entries,user_data=None) actiongroup.add_toggle_actions(entries,user_data=None) actiongroup.add_radio_actions(entries,value=0,on_change=None,user_data=None)
More about these later but first I'll describe how to use an
Action with a Button to
illustrate the basic operations of connecting an
Action to a proxy widget.
The basic procedure for using an Action
with a Button proxy is illustrated by the simpleaction.py example program. The
Button is connected to the
Action using the method:
action.connect_proxy(proxy)
where proxy is a MenuItem,
ToolItem or Button
widget.
An Action has one signal the "activate"
signal that is triggered when the Action is activated
usually as the result of a proxy widget being activated (for example a
ToolButton is clicked). You just have connect a
callback to this signal to handle the activation of any of the proxy
widgets.
The source code for the simpleaction.py example program is:
1 #!/usr/bin/env python
2
3 import pygtk
4 pygtk.require('2.0')
5 import gtk
6
7 class SimpleAction:
8 def __init__(self):
9 # Create the toplevel window
10 window = gtk.Window()
11 window.set_size_request(70, 30)
12 window.connect('destroy', lambda w: gtk.main_quit())
13
14 # Create an accelerator group
15 accelgroup = gtk.AccelGroup()
16 # Add the accelerator group to the toplevel window
17 window.add_accel_group(accelgroup)
18
19 # Create an action for quitting the program using a stock item
20 action = gtk.Action('Quit', None, None, gtk.STOCK_QUIT)
21 # Connect a callback to the action
22 action.connect('activate', self.quit_cb)
23
24 # Create an ActionGroup named SimpleAction
25 actiongroup = gtk.ActionGroup('SimpleAction')
26 # Add the action to the actiongroup with an accelerator
27 # None means use the stock item accelerator
28 actiongroup.add_action_with_accel(action, None)
29
30 # Have the action use accelgroup
31 action.set_accel_group(accelgroup)
32
33 # Connect the accelerator to the action
34 action.connect_accelerator()
35
36 # Create the button to use as the action proxy widget
37 quitbutton = gtk.Button()
38 # add it to the window
39 window.add(quitbutton)
40
41 # Connect the action to its proxy widget
42 action.connect_proxy(quitbutton)
43
44 window.show_all()
45 return
46
47 def quit_cb(self, b):
48 print 'Quitting program'
49 gtk.main_quit()
50
51 if __name__ == '__main__':
52 sa = SimpleAction()
53 gtk.main()
The example creates an Action (line 20)
that uses a Stock Item to provide the label text with mnemonic, icon,
accelerator and translation domain. If a Stock Item is not used you'll need
to specify a label instead. Line 22 connects the "activate" signal of
action to the self.quit_cb()
method so that it is invoked when the Action is
activated by quitbutton. Line 42 connects
quitbutton to action as a
proxy widget. When quitbutton is clicked it will
activate action and thereby invoke the
self.quit_cb() method. The simpleaction.py example uses quite a
bit of code (lines 15, 17, 31 and 34 to setup the accelerator for the
Button. The procedure is similar for
MenuItems and Toolbar
ToolItems.
Figure 16.1, “Simple Action Example” shows the simpleaction.py example in operation.
In the previous section we saw that an existing widget could be
connected to an Action as a proxy. In this section
we'll see how a proxy widget can be created using the
Action methods:
menuitem = action.create_menu_item() toolitem = action.create_tool_item()
The basicaction.py
example illustrates a MenuItem,
ToolButton and a Button
sharing an Action. The
MenuItem and the ToolButton
are created using the above methods. The basicaction.py example program source
code is:
1 #!/usr/bin/env python
2
3 import pygtk
4 pygtk.require('2.0')
5 import gtk
6
7 class BasicAction:
8 def __init__(self):
9 # Create the toplevel window
10 window = gtk.Window()
11 window.connect('destroy', lambda w: gtk.main_quit())
12 vbox = gtk.VBox()
13 vbox.show()
14 window.add(vbox)
15
16 # Create an accelerator group
17 accelgroup = gtk.AccelGroup()
18 # Add the accelerator group to the toplevel window
19 window.add_accel_group(accelgroup)
20
21 # Create an action for quitting the program using a stock item
22 action = gtk.Action('Quit', '_Quit me!', 'Quit the Program',
23 gtk.STOCK_QUIT)
24 action.set_property('short-label', '_Quit')
25 # Connect a callback to the action
26 action.connect('activate', self.quit_cb)
27
28 # Create an ActionGroup named BasicAction
29 actiongroup = gtk.ActionGroup('BasicAction')
30 # Add the action to the actiongroup with an accelerator
31 # None means use the stock item accelerator
32 actiongroup.add_action_with_accel(action, None)
33
34 # Have the action use accelgroup
35 action.set_accel_group(accelgroup)
36
37 # Create a MenuBar
38 menubar = gtk.MenuBar()
39 menubar.show()
40 vbox.pack_start(menubar, False)
41
42 # Create the File Action and MenuItem
43 file_action = gtk.Action('File', '_File', None, None)
44 actiongroup.add_action(file_action)
45 file_menuitem = file_action.create_menu_item()
46 menubar.append(file_menuitem)
47
48 # Create the File Menu
49 file_menu = gtk.Menu()
50 file_menuitem.set_submenu(file_menu)
51
52 # Create a proxy MenuItem
53 menuitem = action.create_menu_item()
54 file_menu.append(menuitem)
55
56 # Create a Toolbar
57 toolbar = gtk.Toolbar()
58 toolbar.show()
59 vbox.pack_start(toolbar, False)
60
61 # Create a proxy ToolItem
62 toolitem = action.create_tool_item()
63 toolbar.insert(toolitem, 0)
64
65 # Create and pack a Label
66 label = gtk.Label('''
67 Select File->Quit me! or
68 click the toolbar Quit button or
69 click the Quit button below or
70 press Control+q
71 to quit.
72 ''')
73 label.show()
74 vbox.pack_start(label)
75
76 # Create a button to use as another proxy widget
77 quitbutton = gtk.Button()
78 # add it to the window
79 vbox.pack_start(quitbutton, False)
80
81 # Connect the action to its proxy widget
82 action.connect_proxy(quitbutton)
83 # Have to set tooltip after toolitem is added to toolbar
84 action.set_property('tooltip', action.get_property('tooltip'))
85 tooltips = gtk.Tooltips()
86 tooltips.set_tip(quitbutton, action.get_property('tooltip'))
87
88 window.show()
89 return
90
91 def quit_cb(self, b):
92 print 'Quitting program'
93 gtk.main_quit()
94
95 if __name__ == '__main__':
96 ba = BasicAction()
97 gtk.main()
This example introduces an ActionGroup to
hold the Actions used in the program. Section 16.1.2, “ActionGroups” will go into more detail on the use of
ActionGroups.
The code in lines 9-14 sets up a top level window containing a
VBox. Lines 16-35 set up the "Quit"
Action similar to that in the simpleaction.py example program and
add it with the gtk.STOCK_QUIT Stock Item accelerator
(line 32) to the "BasicAction" ActionGroup (created
in line 29). Note that, unlike the simpleaction.py example program, you
don't have to call the connect_accelerator() method
for the action since it is called automatically when the
create_menu_item() method is called in line
53.
Lines 38-40 create a MenuBar and pack it
into the VBox. Lines 43-44 create an
Action (file_action) for the
menu and add it to
actiongroup. The and
menu items are created in lines 45 and 53
and added to menubar and
file_menu respectively in lines 46 and 54.
Likewise a Toolbar is created and added
to the VBox in lines 57-59. The proxy
ToolItem is created and added to
toolbar in lines 62-63. Note the
Action tooltip must be set (line 84) after the
ToolItem is added to the
Toolbar for it to be used. Also the
Button tooltip must be added manually (lines
84-86).
Figure 16.2, “Basic Action Example” displays the basicaction.py example program in operation:
A proxy widget can be disconnected from an
Action by using the method:
action.disconnect_proxy(proxy)
An Action has a number of properties that
control the display and function of its proxy widgets. The most important of
these are the "sensitive" and "visible" properties. The "sensitive" property
determines the sensitivity of the proxy widgets. If "sensitive" is
FALSE the proxy widgets are not activatable and will
usually be displayed "grayed out". Likewise, the "visible" property
determines whether the proxy widgets will be visible. If an
Action's "visible" property is
FALSE its proxy widgets will be hidden.
As we'll see in the next section, an
Action's sensitivity or visibility is also controlled
by the sensitivity or visibility of the ActionGroup
it belongs to. Therefore, for an Action to be
sensitive (or visible) both it and its ActionGroup
must be sensitive (or visible). To determine the effective sensitivity or
visibility of an Action you should use the following
methods:
result = action.is_sensitive() result = action.is_visible()
The name assigned to an Action is
contained in its "name" property which is set when the
Action is created. You can retrieve that name using
the method:
name = action.get_name()
Other properties that control the display of the proxy widgets
of an Action include:
"hide-if-empty" | If TRUE, empty menu proxies for this
action are hidden. |
"is-important" | If TRUE,
ToolItem proxies for this action show text in
gtk.TOOLBAR_BOTH_HORIZ mode. |
"visible-horizontal" | If TRUE, the
ToolItem is visible when the toolbar is in a
horizontal orientation. |
"visible-vertical" | If TRUE, the
ToolItem is visible when the toolbar is in a vertical
orientation. |
Other properties of interest include:
"label" | The label used for menu items and buttons that activate this action. |
"short-label" | A shorter label that may be used on toolbar buttons and buttons. |
"stock-id" | The Stock Item to be used to retrieve the icon, label and accelerator to be used in widgets representing this action. |
"tooltip" | A tooltip for this action. |
Note that the basicaction.py example program
overrides the gtk.STOCK_QUIT label with "_Quit me!" and
sets the "short-label" property to "_Quit". The short label is used for the
ToolButton and the Button
labels but the full label is used for the MenuItem
label. Also note that the tooltip cannot be set on a
ToolItem until it is added to a
Toolbar.
An Action has three methods that are used
to set up an accelerator:
action.set_accel_group(accel_group) action.set_accel_path(accel_path) action.connect_accelerator()
These, in conjunction with the
gtk.ActionGroup.add_action_with_accel() method,
should cover most cases of accelerator set up.
An AccelGroup must always be set for an
Action. The set_accel_path()
method is called by the
gtk.ActionGroup.add_action_with_accel() method. If
set_accel_path() is used the accelerator path
should match the default format:
"<Actions>/actiongroup_name/action_name". Finally, the
connect_accelerator() method is called to complete
the accelerator set up.
An Action must have an
AccelGroup and an accelerator path associated with it
before connect_accelerator() is called.
Since the connect_accelerator() method
can be called several times (i.e. once for each proxy widget), the number of
calls is counted so that an equal number of
disconnect_accelerator() calls must be made before
removing the accelerator.
As illustrated in the previous example programs, an
Action accelerator can be used by all the proxy
widgets. An Action should be part of an
ActionGroup in order to use the default accelerator
path that has the format:
"<Actions>/actiongroup_name/action_name". The easiest way to add an
accelerator is to use the
gtk.ActionGroup.add_action_with_accel() method and
the following general procedure:
AccelGroup and add it to
the top level window.ActionGroupAction specifying a
Stock Item with an accelerator.Action to the
ActionGroup using the
gtk.ActionGroup.add_action_with_accel() method
specifying None to use the Stock Item accelerator or an
accelerator string acceptable to
gtk.accelerator_parse().AccelGroup for the
Action using the
gtk.Action.set_accel_group() method.gtk.Action.connect_accelerator() method.Any proxy widgets created by or connected to the
Action will use the accelerator.
As mentioned previously a ToggleAction is
a subclass of Action that can be toggled between two
states. The constructor for a ToggleAction takes the
same parameters as an Action:
toggleaction = gtk.ToggleAction(name,label,tooltip,stock_id)
In addition to the Action methods the
following ToggleAction methods:
toggleaction.set_active(is_active)
is_active = toggleaction.get_active()
set and get the current state of
toggleaction. is_active is a
boolean value.
You can connect to the "toggled" signal specifying a callback with the signature:
def toggled_cb(toggleaction,user_data)
The "toggled" signal is emitted when the
ToggleAction changes state.
A MenuItem proxy widget of a
ToggleAction will be displayed like a
CheckMenuItem by default. To have the proxy
MenuItem displayed like a
RadioMenuItem set the "draw-as-radio" property to
TRUE using the method:
toggleaction.set_draw_as_radio(draw_as_radio)
You can use the following method to determine whether the
ToggleAction MenuItems will be
displayed like RadioMenuItems:
draw_as_radio = toggleaction.get_draw_as_radio()
A RadioAction is a subclass of
ToggleAction that can be grouped so that only one
RadioAction is active at a time. The corresponding
proxy widgets are the RadioMenuItem and
RadioToolButton.
The constructor for a RadioAction takes
the same arguments as an Action with the addition of
a unique integer value that is used to identify the active
RadioAction in a group:
radioaction = gtk.RadioAction(name,label,tooltip,stock_id,value)
The group for a RadioAction can be set
using the method:
radioaction.set_group(group)
where group is another
RadioAction that radioaction
should be grouped with. The group containing a
RadioAction can be retrieved using the method:
group = radioaction.get_group()
that returns a list of the group of
RadioAction objects that includes
radioaction.
The value of the currently active group member can retrieved using the method:
active_value = radioaction.get_current_value()
You can connect a callback to the "changed" signal to be
notified when the active member of the RadioAction
group has been changed. Note that you only have to connect to one of the
RadioAction objects to track changes. The callback
signature is:
def changed_cb(radioaction,current,user_data)
where current is the currently active
RadioAction in the group.
The actions.py example
program illustrates the use of the Action,
ToggleAction and RadioAction
objects. Figure 16.3, “Actions Example” displays the example
program in operation:
This example is similar enough to the basicaction.py example program that a detailed description is not necessary.
As mentioned in the previous section, related
Action objects should be added to an
ActionGroup to provide common control over their
visibility and sensitivity. For example, in a text processing application
the menu items and toolbar buttons for specifying the text justification
could be contained in an ActionGroup. A user
interface is expected to have multiple ActionGroup
objects that cover various aspects of the application. For example, global
actions like creating new documents, opening and saving a document and
quitting the application likely form one ActionGroup
while actions such as modifying the view of the document would form
another.
An ActionGroup is created using the
constructor:
actiongroup = gtk.ActionGroup(name)
where name is a unique name for the
ActionGroup. The name should be unique because it is
used to form the default accelerator path for its
Action objects.
The ActionGroup name can be retrieved
using the method:
name = actiongroup.get_name()
or by retrieving the contents of the "name" property.
As illustrated in Section 16.1.1, “Actions” an
existing Action can be added to an
ActionGroup using one of the methods:
actiongroup.add_action(action) actiongroup.add_action_with_accel(action,accelerator)
where action is the
Action to be added and
accelerator is a string accelerator specification
acceptable to gtk.accelerator_parse(). If
accelerator is None the
accelerator (if any) associated with the "stock-id" property of
action will be used. As previously noted the
add_action_wih_accel() method is preferred if you
want to use accelerators.
The ActionGroup offers three convenience
methods that make the job of creating and adding
Action objects to an
ActionGroup much easier:
actiongroup.add_actions(entries,user_data=None) actiongroup.add_toggle_actions(entries,user_data=None) actiongroup.add_radio_actions(entries,value=0,on_change=None,user_data=None)
The entries parameter is a sequence of
action entry tuples that provide the information used to create the actions
that are added to the ActionGroup. The
RadioAction with the value of
value is initially set
active. on_change is a callback that is connected to
the "changed" signal of the first RadioAction in the
group. The signature of on_changed is:
def on_changed_cb(radioaction,current,user_data)
The entry tuples for Action objects
contain:
None if a label is specified.None if a stock id is specified.gtk.accelerator_parse() function. Optional with a
default value of None.None.None.You must minimally specify a value for the
name field and a value in either the stock
id field or the label field. If you
specify a label then you can specify None for the stock
id if you aren't using one. For example the following method call:
actiongroup.add_actions([('quit', gtk.STOCK_QUIT, '_Quit me!', None,
'Quit the Program', quit_cb)])
adds an action to actiongroup for
exiting a program.
The entry tuples for the ToggleAction
objects are similar to the Action entry tuples except
there is an additional optional flag field containing
a boolean value indicating whether the action is active. The default value
for the flag field is FALSE. For
example the following method call:
actiongroup.add_toggle_actions([('mute, None, '_Mute', '<control>m',
'Mute the volume', mute_cb, True)])
adds a ToggleAction to
actiongroup and sets it to be initially
active.
The entry tuples for the RadioAction
objects are similar to the Action entry tuples but
specify a value field instead of a
callback field:
None if a label is specified.None if a stock id is specified.gtk.accelerator_parse() function. Optional with a
default value of None.None.0. Should always be specified in
applications.For example the following code fragment:
radioactionlist = [('am', None, '_AM', '<control>a', 'AM Radio', 0)
('fm', None, '_FM', '<control>f', 'FM Radio', 1)
('ssb', None, '_SSB', '<control>s', 'SSB Radio', 2)]
actiongroup.add_radio_actions(radioactionlist, 0, changed_cb)
creates three RadioAction objects and
sets the initial active action to 'am' and the callback that is invoked when
any of the actions is activated to changed_cb.
An Action can be retrieved by name from
an ActionGroup by using the method:
action = actiongroup.get_action(action_name)
A list of all the Action objects
contained in an ActionGroup can be retrieved using
the method:
actionlist = actiongroup.list_actions()
The sensitivity and visibility of all
Action objects in an
ActionGroup can be controlled by setting the
associated property values. The following convenience methods get and set
the properties:
is_sensitive = actiongroup.get_sensitive() actiongroup.set_sensitive(sensitive) is_visible = actiongroup.get_visible() actiongroup.set_visible(visible)
Finally you can remove an Action from an
ActionGroup using the method:
actiongroup.remove_action(action)
The actiongroup.py
example program duplicates the menubar and toolbar of the actions.py example program using the
ActionGroup methods. In addition the program provides
buttons to control the sensitivity and visibility of the menu items and
toolbar items. Figure 16.4, “ActionGroup Example” illustrates the
program in operation:
Your application can track the connection and removal of proxy
widgets to the Action objects in an
ActionGroup using the "connect-proxy" and
disconnect-proxy" signals. The signatures of your signal handler callbacks
should be:
def connect_proxy_cb(actiongroup,action,proxy,user_params) def disconnect_proxy_cb(actiongroup,action,proxy,user_params)
For example, you might want to track these changes to make some additional changes to the properties of the new proxy widget when it is connected or to update some other part of the user interface when a proxy widget is disconnected.
The "pre-activate" and "post-activate" signals allow your application to do some additional processing immediately before or after an action is activated. The signatures of the signal handler callbacks should be:
def pre_activate_cb(actiongroup, action, user_params) def post_activate_cb(actiongroup, action, user_params)
These signals are mostly used by the
UIManager to provide global notification for all
Action objects in ActionGroup
objects used by it.