PyQt provides two mechanisms for dealing with events: the high-level signals and slots mechanism, and low-level event handlers. The signals and slots approach is ideal when we are concerned with what actions the user wants to perform, without getting bogged down in the details of how specifically they asked. Signals and slots can also be used to customize some aspects of how widgets behave. But when we need to go deeper, particularly when creating custom widgets, we need to use low-level event handlers.
PyQt provides a rich variety of event handlers, some concerned with widget behavior, such as those that handle key presses and mouse events, and others concerned with widget appearance, such as those that handle paint events and resize events.
PyQt's event-handling mechanism works in the logical way we would expect. For example, if the user clicks the mouse or presses a key on a widget with key
Signals and slots
board focus, the widget is given the event. If the widget handles the event, that is the end of the story. But if the widget does not handle the event, the event is propagated to the widget's parent—another benefit of PyQt's parent-child hierarchy. This passing of unhandled events from child to parent continues right up to the top-level widget, and if that doesn't handle the event, the event is simply thrown away.
PyQt provides five different ways of intercepting and handling events. The first two approaches are the most heavily used, with the others needed rarely, if ever.
The simplest approach is to reimplement a specific event handler. So far, we have seen just one example of this: the reimplementation of a widget's closeEvent(). As we will see in this chapter and in subsequent chapters, we can control a widget's behavior by reimplementing other event handlers—for example, keyPressEvent(), mousePressEvent(), and mouseReleaseEvent(). We can also control a widget's appearance by reimplementing resizeEvent() and paintEvent(). When we reimplement these events we often don't call the base class implementation since we want our own code executed only as a result of the event handler being called.
Before any specific event handler is called, the event() event handler is called. Reimplementing this method allows us to handle events that cannot be handled properly in the specific event handlers (in particular, overriding the Tab key's keyboard focus changing behavior), or to implement events for which no specific handler exists, such as QEvent.ToolBarChange. When we reimplement this handler, we call the base class implementation for any events we don't handle ourselves.
The third and fourth approaches use event filters. We can call installEvent-Filter() on any QObject. This will mean that all events for the QObject are passed to our event filter first: We can discard or modify any of the events before they reach the target object. An even more powerful version of this approach is to install an event filter on the QApplication object, although its only practical uses are for debugging and for handling mouse events sent to disabled widgets. It is possible to install multiple event filters on an object or on QAp-plication, in which case they are executed in order from most to least recently installed.
Event filters provide a very powerful means of handling events, and newcomers to PyQt programming are often tempted to use them. But we recommend avoiding the use of event filters, at least until you have a lot of PyQt programming experience. If very large numbers of event filters are installed, application performance can suffer; also, they can considerably increase code complexity compared with simply reimplementing specific event handlers, or the event() handler. We will not look at any event filter examples, since they should be avoided in general PyQt programming—they are really relevant only when creating custom widgets—and even then they are rarely necessary.
The fifth approach is to subclass QApplication and reimplement its notify() method. This method is called before any event filter or event handler, so it provides the ultimate in control. In practice, this would be done only for debugging, and even then, using event filters is probably more flexible.
Was this article helpful?
Discover How You Can Quickly And Easily Dominate Google and YouTube... With Simple Cash Generating Videos. Did you know that YouTube is the second largest search website on the entire Internet? YouTube gets more daily searches than Bing and Yahoo. In fact, there is only one search engine that gets more action.