Erste Programme in PyQt4
In diesem Abschnitt des PyQt4-Tutorials lernen wir etwas über grundlegende Funktionen. Dabei wird so langsam erklärt, als wenn man mit einem Kinde sprechen würde. Die ersten Schritte eines Kindes sind unbeholfen - genau so ist es auch für einen Programmieranfänger. Erinnern Sie sich: Es gibt keine dummen Menschen - nur faule und solche, die nicht ausdauernd genug sind.
Einfaches Beispiel
Das folgende Codebeispiel ist sehr vereinfacht. Es zeigt lediglich ein kleines Fenster. Und doch können wir bereits eine Menge mit diesem Fenster machen: Wir können seine Größe ändern, vergrößern und verkleinern. Dafür braucht es eine Menge Code. Jemand hat das bereits übernommen. Weil es sich diese Funktionalität in den meisten Anwendungen wiederholt, macht es keinen Sinn, es immer und immer wieder zu schreiben. Darum wurde es vor dem Programmierer versteckt. Python ist ein Toolset auf hoher Ebene. Würden wir mit einem Toolkit niedrigerer Ebene programmieren, würde das folgende Codebeispiel leicht Dutzende Zeilen umfassen.
#!/usr/bin/python
# simple.py
import sys
from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
widget = QtGui.QWidget()
widget.resize(250, 150)
widget.setWindowTitle('simple')
widget.show()
sys.exit(app.exec_())
import sys from PyQt4 import QtGui
Hier nehmen wir die nötigen Importe vor. Die grundlegenden GUI-Widgets befinden sich im QtGui-Modul.
app = QtGui.QApplication(sys.argv)
Jede PyQt4-Anwendung muss ein application-Objekt erzeugen. Das application-Objekt befindet sich im QtGui-Modul. Der sys.argv-Parameter ist eine Liste von Argumenten von der Kommandozeile. Python-Skripte können über die Shell (Kommandozeile) gestartet werden. Auf diese Weise können wir den Aufruf unserer Skripte kontrollieren.
widget = QtGui.QWidget()
Das QWidget-Widget ist die Basisklasse aller Benutzeroberflächenobjekte in PyQt4. Wir verwenden den Default-Konstruktor von QWidget. Der Default-Konstruktor hat keine Elternklasse (parent). Ein Widget ohne Elternklasse heißt Fenster.
widget.resize(250, 150)
Die resize()-Methode passt die Widget-Größe an. Sie beträgt 250px in der Breite und 150px in der Höhe.
widget.setWindowTitle('simple')
Hier setzen wir den Titel unseres Fensters, der jetzt in der Titelzeile angezeigt wird.
widget.show()
Die show()-Methode zeigt das Widget auf dem Bildschirm an.
sys.exit(app.exec_())
Zum Schluss betreten wir die Hauptschleife der Anwendung. Die Event-Behandlung beginnt an dieser Stelle. Die Hauptschleife empfängt Events vom Windowsystem und überträgt sie an die Anwendungswidgets. Die Hauptschleife endet, wenn wir die exit()-Methode aufrufen oder das Hauptwidget zerstört wird. Die sys.exit()-Methode garantiert eine saubere Beendigung. Die Umgebung wird informiert, wie die Anwendung beendet wurde.
Fragen Sie sich, warum die exec_()-Methode einen Unterstrich hat? Alles hat seine Bedeutung. Offensichtlich hat sie ihn, da es sich bei exec um ein Python Schlüsselwort handelt. Darum wurde hier statt dessen exec_() verwendet.
Abbildung: Einfaches Beispiel
Ein Anwendungs-Icon
Das Anwendungs-Icon ist ein kleines Bild, das gewöhnlich in der linken oberen Ecke der Titelzeile angezeigt wird. Das folgende Beispiel zeigt, wie das in PyQt4 gemacht wird. Wir werden darüber hinaus einige neue Methoden kennenlernen.
#!/usr/bin/python
# icon.py
import sys
from PyQt4 import QtGui
class Icon(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Icon')
self.setWindowIcon(QtGui.QIcon('icons/web.png'))
app = QtGui.QApplication(sys.argv)
icon = Icon()
icon.show()
sys.exit(app.exec_())
Das Beispiel wurde im prozeduralen Stil geschrieben. Die Python Programmiersprache unterstützt sowohl prozeduralen als auch objektorientierten Programmierstil. In PyQt4 zu programmieren, setzt objektorientiertes Programmieren (OOP) voraus.
class Icon(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
Die drei wichtigsten Dinge beim OOP sind Klassen, Eigenschaften und Methoden. Im Beispiel erzeugen wir eine neue Klasse names Icon. Die Icon-Klasse erbt von der QtGui.QWidget-Klasse. Das bedeutet, dass wir zwei Konstruktoren aufrufen müssen. Die erste für die Icon-Klasse, die zweite für die geerbte Klasse.
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Icon')
self.setWindowIcon(QtGui.QIcon('icons/web.png'))
Alle drei Methoden wurden von der QtGui.QWidget-Klasse geerbt. Die setGeometry()-Methode macht zwei Dinge: Sie lokalisiert das Fenster auf dem Bildschirm und setzt die Fenstergröße. Die ersten zwei Parameter sind die x- und y-Positionen des Fensters. Die dritte erfasst die Weite, die vierte seine Höhe. Die letzte Methode bestimmt das Anwendungs-Icon. Dazu haben wir eine QIcon-Objekt erzeugt, das den Pfad zu unserem anzuzeigenden Icon erhält.
Abbildung: Icon
Anzeige eines Tooltips
Wir können für jedes unserer Widgets eine Ballon-Hilfe erzeugen.
#!/usr/bin/python
# tooltip.py
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class Tooltip(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Tooltip')
self.setToolTip('This is a <b>QWidget</b> widget')
QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))
app = QtGui.QApplication(sys.argv)
tooltip = Tooltip()
tooltip.show()
sys.exit(app.exec_())
In diesem Beispiel zeigen wir einen Tooltip für ein QWidget-Widget.
self.setToolTip('This is a <b>QWidget</b> widget')
Um einen Tooltip zu erzeugen, rufen wir die setTooltip()-Methode auf. Wir können dabei Richt-Text-Formatierung verwenden.
QtGui.QToolTip.setFont(QtGui.QFont('OldEnglish', 10))
Da die Standardschrift des QToolTip nicht gut aussieht, ändern wir diese.
Abbildung: Tooltip
Schließen eines Fensters
Der offensichtliche Weg, ein Fenster zu schließen, ist, auf die x-Schaltfläche in der Titelzeile zu klicken. Im nächsten Beispiel wollen wir zeigen, wie man über das Programm selbst unser Fenster schließen kann. Wir werden dabei kurz auf Signale und Slots eingehen.
Als nächstes kommt der Konstruktor eines QPushButton, den wir in unserem Beispiel verwenden werden.
QPushButton(string text, QWidget parent = None)
Der text-Parameter ist der Schriftzug, der auf dem Knopf angezeigt wird. Bei parent handelt es sich um das Herkunftsobjekt, auf dem unser Knopf platziert wird - in diesem Fall das QWidget.
#!/usr/bin/python
# quitbutton.py
import sys
from PyQt4 import QtGui, QtCore
class QuitButton(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
quit = QtGui.QPushButton('Close', self)
quit.setGeometry(10, 10, 60, 35)
self.connect(quit, QtCore.SIGNAL('clicked()'),
QtGui.qApp, QtCore.SLOT('quit()'))
app = QtGui.QApplication(sys.argv)
qb = QuitButton()
qb.show()
sys.exit(app.exec_())
quit = QtGui.QPushButton('Close', self)
quit.setGeometry(10, 10, 60, 35)
Wir erzeugen einen Druckknopf und positionieren ihn auf dem QWidget auf dieselbe Weise, wie wir es vorher mit dem Widget selbst auf dem Bildschirm getan haben.
self.connect(quit, QtCore.SIGNAL('clicked()'),
QtGui.qApp, QtCore.SLOT('quit()'))
Das Ereignisverarbeitungssystem funktioniert in PyQt4 mit einem Signal&Slot-Mechanismus. Wenn wir auf den Knopf drücken, wird das Signal clicked() geworfen. Der Slot kann ein PyQt-Slot sein oder jeder Pythonaufruf. Die QtCore.QObject.connect()-Methode verbindet Signale mit Slots. In unserem Fall ist der Slot ein vordefinierter PyQt-quit()-Slot. Die Kommunikation findet zwischen zwei Objekten, nämlich dem Sender und dem Empfänger, statt. Der Sender ist der Druckknopf, der Empfänger das Anwendungsobjekt.
Abbildung: Beenden-Schaltfläche
Mitteilungsbox
Standardmäßig schließt sich das QWidget, wenn wir den x-Knopf in der Titelzeile anklicken. Manchmal wollen wir dieses Standardverhalten ändern. Zum Beispiel, wenn wir eine Datei in einem Editor geöffnet und geändert haben. Wir zeigen eine Mitteilungsbox, um die Aktion bestätigen zu lassen.
#!/usr/bin/python
# messagebox.py
import sys
from PyQt4 import QtGui
class MessageBox(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('message box')
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
app = QtGui.QApplication(sys.argv)
qb = MessageBox()
qb.show()
sys.exit(app.exec_())
Wenn wir das QWidget schließen, wird das QCloseEvent erzeugt. Um das Widgetverhalten zu verändern, müssen wir den event() Eventhandler überschreiben.
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
Wir zeigen eine Mitteilungsbox mit zwei Knöpfen - Ja und Nein. Der erste String erscheint in der Titelzeile, der zweite ist die Nachricht, die vom Dialog angezeigt wird. Der Rückgabewert wird in der reply-Variablen gespeichert.
if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
Hier prüfen wir den Rückgabewert. Wenn wir den Ja-Knopf anwählen, nehmen wir das Ereignis an, was uns zum Schließen des Widgets führt und zur Beendigung der Anwendung. Andernfalls ignorieren wir das close-Ereignis.
Abbildung: Mitteilungsbox
Fensterzentrierung auf dem Bildschirm
Das folgende Skript zeigt, wie man ein Fenster auf einer Desktopoberfläche zentrieren kann.
#!/usr/bin/python
# center.py
import sys
from PyQt4 import QtGui
class Center(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setWindowTitle('center')
self.resize(250, 150)
self.center()
def center(self):
screen = QtGui.QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
app = QtGui.QApplication(sys.argv)
qb = Center()
qb.show()
sys.exit(app.exec_())
self.resize(250, 150)
An dieser Stelle wird das QWidget auf 250px Breite und 150px Höhe eingestellt.
screen = QtGui.QDesktopWidget().screenGeometry()
Wir finden die Bildschirmauflösung des Monitors heraus.
size = self.geometry()
Hier holen wir uns die Größe unseres QWidgets.
self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
Hier bewegen wir das Fenster in die Mitte des Bildschirms.