Figure 6.6 The Edit toolbar
The pattern for adding widgets to a toolbar is always the same: We create the widget, set it up, connect it to something to handle user interaction, and add it to the toolbar. We have made the spinbox an instance variable because we will need to access it outside the main window's initializer. The addWidget() call passes ownership of the spinbox to the toolbar.
We have now fully populated the menus and toolbars with actions. Although every action was added to the menus, some were not added to the toolbars. This is quite conventional; usually only the most frequently used actions are added to toolbars.
Earlier we saw the following line of code:
This tells PyQt that if actions are added to the imageLabel widget, they are to be used for a context menu, such as the one shown in Figure 6.7.
self.addActions(self.imageLabel, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction))
We can reuse our addActions() method to add actions to the label widget, providing we don't pass Nones since QWidget does not have an addSeparator() method. Setting the policy and adding actions to a widget are all that is necessary to get a context menu for that widget.
Invert |H| 5wap Red and Blue | Unmirror D Mirror Vertically Mirror Horizontally
Ctrl+I Ctrl+A Ctrl+U Ctrl+V Ctrl+H
Figure 6.7 The Image Label's context menu
The QWidget class has an addAction() method that is inherited by the QMenu, QMenuBar, and QToolBar classes. This is why we can add actions to any of these classes. Although the QWidget class does not have an addSeparator() method, one is provided for convenience in the QMenu, QMenuBar, and QToolBar classes. If we want to add a separator to a context menu, we must do so by adding a separator action. For example:
separator = QAction(self) separator.setSeparator(True) self.addActions(editToolbar, (editInvertAction, editSwapRedAndBlueAction, separator, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction))
If we need more sophisticated context menu handling—for example, where the context-
menu's actions vary depending on the application's state, we can reimplement the relevant widget's contextMenuEvent() event-handling method. Event handling is covered in Chapter 10.
When we create a new image or load an existing image, we want the user interface to revert to its original state. In particular, we want the "edit invert" and "edit swap red and green" actions to be "off", and the mirror action to be "edit unmirrored".
self.resetableActions = ((editInvertAction, False),
(editSwapRedAndBlueAction, False), (editUnMirrorAction, True))
We have created an instance variable holding a tuple of pairs, with each pair holding an action and the checked state it should have when a new image is created or loaded. We will see resetableActions in use when we review the fileNew() and loadFile() slots.
In the Image Changer application, all of the actions are enabled all of the En-
time. This is fine, since we always check for a null image before performing abling any action, but it has the disadvantage that, for example, "file save" will be aDnisd-
enabled if there is no image or if there is an unchanged image, and similarly, abling the edit actions will be enabled even if there is no image. The solution is to Actions enable or disable actions depending on the application's state, as the sidebar in sidebar
Chapter 13 shows. » 385
Was this article helpful?