Base classes

You won't often create objects from Qt base classes, but you might need to subclass QObject now and then. The basic classes that Qt is built on are QObject and QEvent. There are several other classes used for the construction of high-level datatypes, and a large number of other classes that support working with, for instance, fonts, images and colors.

QObject brings together support for:

Signals and slots are meant for communication between objects—for instance, when a button is pressed, certain other objects must be notified. Events, on the other hand, notify objects of general actions of the user, such as key presses or mouse movements; events do not necessarily originate with objects.

The linchpin of the event handling mechanism is the class representing the information associated with an event, such as the position of the mouse. This is the QEvent class; there are a whole slew of specialized subclasses like QPaintEvent, QFocusEvent, QMouseEvent, QWheelEvent and QKeyEvent that do the rounds of all interested objects. For instance, a keypress is first passed to the application object, based on QApplication. From there it trickles down the whole widget ownership hierarchy until one widget ‘consumes' it —that is, reacts to the event and doesn't send it on by calling the event(QEvent) method.

See the next listing for an example of reacting to mouse presses and movements. Note also that if the window is obscured and remapped, the paintEvent method is fired— this will obliterate your whole beautiful drawing.

Example 10-1. event1.py - handling mouse events in PyQt

#
# event1.py
#
from qt import *
import sys

class Painting(QWidget):

    def __init__(self, *args):
        apply(QWidget.__init__,(self, ) + args)

    def paintEvent(self, ev):
        self.p = QPainter()
        self.p.begin(self)
        self.p.fillRect(self.rect(), QBrush(Qt.white))
        self.p.flush()
        self.p.end()

    def mouseMoveEvent(self, ev):
        self.p = QPainter()
        self.p.begin(self)
        self.p.drawLine(self.currentPos, ev.pos())
        self.currentPos=QPoint(ev.pos())
        self.p.flush()
        self.p.end()

    def mousePressEvent(self, ev):
        self.p = QPainter()
        self.p.begin(self)
        self.p.drawPoint(ev.pos())
        self.currentPos=QPoint(ev.pos())

        self.p.flush()
        self.p.end()

class MainWindow(QMainWindow):

    def __init__(self, *args):
        apply(QMainWindow.__init__, (self,) + args)
        self.painting=Painting(self)
        self.setCentralWidget(self.painting)

def main(args):
    app=QApplication(args)
    win=MainWindow()
    win.show()
    app.connect(app, SIGNAL("lastWindowClosed()"),
                app, SLOT("quit()"))
    app.exec_loop()

if __name__=="__main__":
    main(sys.argv)
      

event1.py

In handling methods such as mousePressEvent(), It is customary to use ev as the name for the QEvent parameter. In this example, all mouse press events and mouse move events are consumed by the Painting class.