Main-window-style applications are created by subclassing QMainWindow. The window has a single widget (which may be composite and so contain other widgets) as its central widget.
Actions are used to represent the functionality the application provides to its users. These actions are held as QAction objects which have text (used in menus), icons (used in both menus and toolbars), tooltips and status tips, and that are connected to slots, which, when invoked, will perform the appropriate action. Usually, all the actions are added to the main window's menus, and the most commonly used ones are added to toolbars. To support keyboard users, we provide keyboard shortcuts for frequently used actions, and menu accelerators to make menu navigation as quick and convenient as possible.
Some actions are checkable, and some groups of checkable actions may be mutually exclusive, that is, one and only one may be checked at any one time. PyQt supports checkable actions by the setting of a single property, and supports mutually exclusive groups of actions through QActionGroup objects.
Dock windows are represented by dock widgets and are easy to create and set up. Arbitrary widgets can be added to dock widgets and to toolbars, although in practice we only usually add small or letterbox-shaped widgets to toolbars.
Actions, action groups, and dock windows must all be given a parent explicitly—the main window, for example—to ensure that they are deleted at the right time. This is not necessary for the application's other widgets and QObjects because they are all owned either by the main window or by one of the main window's children. The application's non-QObject objects can be left to be deleted by Python's garbage collector.
Applications often use resources (small files, such as icons, and data files), and PyQt's resource mechanism makes accessing and using them quite easy. They do require an extra build step, though, either using PyQt's pyrcc4 console application, or the mkpyqt.py or Make PyQt programs supplied with the book's examples.
Dialogs can be created entirely in code as we did in the preceding chapter, or using Qt Designer, as we will see in the next chapter. If we need to incorporate Qt Designer user interface files in our application, like resources they require an extra build step, either using PyQt's pyuic4 console application, or again, using mkpyqt.py or Make PyQt.
Once the main window's visual appearance has been created by setting its central widget and by creating menus, toolbars, and perhaps dock windows, we can concern ourselves with loading and saving application settings. Many settings are commonly loaded in the main window's initializer, and settings are normally saved (and the user given the chance to save unsaved changes) in a reimplementation of the closeEvent() method.
If we want to restore the user's workspace, loading in the files they had open the last time they ran the application, it is best to use a single-shot timer at the end of the main window's initializer to load the files.
Most applications usually have a dataset and one or more widgets that are used to present and edit the data. Since the focus of the chapter has been on the main window's user interface infrastructure, we opted for the simplest possible data and visualization widget, but in later chapters the emphasis will be the other way around.
It is very common to have the main window take care of high-level file handling and the list of recently used files, and for the object holding the data to be responsible for loading, saving, and editing the data.
At this point in the book, you now know enough Python and PyQt to create both dialog-style and main-window-style GUI applications. In the next chapter, we will show Qt Designer in action, an application that can considerably speed up the development and maintenance of dialogs. And in the last chapter of Part II, we will explore some of the key approaches to saving and loading custom file formats, using both the PyQt and the Python libraries. In Parts III and IV, we will explore PyQt both more deeply, looking at event handling and creating custom widgets, for example, and more broadly, learning about PyQt's model/view architecture and other advanced features, including threading.
Was this article helpful?