Wer den Einstieg in Qt5 UIs wagen möchte und dabei Python verwendet, der benötigt unter Umständen ein paar kurze Beispiele.
Hier also ein ganz kurzer Überblick was man benötigt um loslegen zu können:
Vorausgesetze Module installieren
pip install pygt5
pip install pyqt5-tools
Wobei die Installation von pyqt5-tools
nur notwendig ist wenn man den Qt Designer nutzen möchte um damit GUIs per Drag and Drop zusammenzuklicken. Aus den Entwürfen werden anschließend XML Dateien mit Endung .ui
generiert die wiederrum im Code referenziert werden können um dynamisch die GUI aufzubauen oder aber man kann sich aus den .ui
Files direkt Pythen Code generieren lassen den man in seiner Anwendung verwendet.
GUI selbst schreiben
Hier ein Beispiel für eine GUI die selbst geschrieben wurde:
#!/usr/bin/python3
import sys
import platform
from PyQt5.QtWidgets import (QWidget, QToolTip, QPushButton, QApplication, QMessageBox, QDesktopWidget)
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtGui import QFont
class Example(QWidget):
# Constructur
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
QToolTip.setFont(QFont('SansSerif', 10))
self.setToolTip('This is a <b>QWidget</b> widget')
# Sample button
btn = QPushButton('Button', self)
btn.setToolTip('This is a <b>QPushButton</b> widget')
btn.resize(btn.sizeHint())
btn.move(10, 10)
# Quit button
qbtn = QPushButton('Quit', self)
qbtn.setToolTip("This button will close the window")
qbtn.clicked.connect(QCoreApplication.instance().quit)
qbtn.resize(qbtn.sizeHint())
qbtn.move(10, 40)
#self.resize(250, 100) # Größe
#self.move(300, 300) # Position
self.setGeometry(300, 300, 300, 200) # Position & Größe
self.setWindowTitle('My Qt5 window on ' + platform.system())
self.center()
self.show()
# Center frame on screen
def center(self):
# Rectangle specifying the geometry of the main window
qr = self.frameGeometry()
# 'QDesktopWidget' provides information about the user's desktop
# Figure out screen resolution of monitor and from this resolution, get center point
cp = QDesktopWidget().availableGeometry().center()
# Set the center of the rectangle to the center of the screen
qr.moveCenter(cp)
# Move top-left point of window to top-left point of qr rectangle,
# thus centering the window on screen
self.move(qr.topLeft())
# Overwrite event to close window
def closeEvent(self, event):
reply = QMessageBox.question(self, 'Message',
"Are you sure to quit?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()
# Check if this script is run as the main module
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
GUI mit Qt Designer erzeugen
Nachfolgend gehen wir davon aus dass wir eine GUI mit Qt Designer erzeugt haben und dabei die XML Datei firstgui.ui
entstanden ist. Die Datei sieht folgendermaßen aus:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>myfirstgui</class>
<widget class="QDialog" name="myfirstgui">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>411</width>
<height>247</height>
</rect>
</property>
<property name="windowTitle">
<string>My First Gui!</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>20</x>
<y>210</y>
<width>381</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
<widget class="QLineEdit" name="myTextInput">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>101</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QListWidget" name="listWidget">
<property name="geometry">
<rect>
<x>120</x>
<y>10</y>
<width>281</width>
<height>192</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="clearBtn">
<property name="geometry">
<rect>
<x>10</x>
<y>180</y>
<width>101</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>clear</string>
</property>
</widget>
<widget class="QPushButton" name="addBtn">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>101</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>add</string>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>myfirstgui</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>258</x>
<y>274</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>myfirstgui</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>clearBtn</sender>
<signal>clicked()</signal>
<receiver>listWidget</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>177</x>
<y>253</y>
</hint>
<hint type="destinationlabel">
<x>177</x>
<y>174</y>
</hint>
</hints>
</connection>
</connections>
</ui>
Mit der XML Datei haben wir jetzt verschiedene Möglichkeiten eine GUI zu generieren.
GUI preview
Zuersteinmal wollen wir sehen wie unsere GUI aussieht ohne dass gleich Python Code generiert wird. Das können wir mit dem Command-line utility pyuic5
machen das durch die Installation von pyqt5-tools
verfügbar wird:
pyuic5 --preview firstgui.ui
Das sollte uns folgende GUI erzeugen:
GUI Python Code generieren
Das können wir mit folgendem Befehl machen:
pyuic5 firstgui.ui
Allerdings hilft uns das nicht viel da der Code in der Konsole erscheint. Wir wollen den Code in einer Datei speichern:
pyuic5 --output firstgui.py firstgui.ui
Damit erzeugen wir eine Datei firstgui.py
die den generierten Code enthält. Das ist schon besser aber dieser Code is nicht ausführbar. Wenn wir ihn verwenden wollen um ihn in unser eigenes Skript zu kopieren, dann ok, aber was wenn wir gleich ein ausführbares Skript haben wollen an dem wir anschließend weiterarbeiten können?
pyuic5 --execute --output firstgui.py firstgui.ui
Jetzt haben wir eine gute Grundlage auf die wir unsere Anwendung aufbauen können und der Code ist direkt ausführbar und sieht so aus:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'firstgui.ui'
#
# Created by: PyQt5 UI code generator 5.9
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_myfirstgui(object):
def setupUi(self, myfirstgui):
myfirstgui.setObjectName("myfirstgui")
myfirstgui.resize(411, 247)
self.buttonBox = QtWidgets.QDialogButtonBox(myfirstgui)
self.buttonBox.setGeometry(QtCore.QRect(20, 210, 381, 32))
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
self.buttonBox.setObjectName("buttonBox")
self.myTextInput = QtWidgets.QLineEdit(myfirstgui)
self.myTextInput.setGeometry(QtCore.QRect(10, 10, 101, 21))
self.myTextInput.setObjectName("myTextInput")
self.listWidget = QtWidgets.QListWidget(myfirstgui)
self.listWidget.setGeometry(QtCore.QRect(120, 10, 281, 192))
self.listWidget.setObjectName("listWidget")
self.clearBtn = QtWidgets.QPushButton(myfirstgui)
self.clearBtn.setGeometry(QtCore.QRect(10, 180, 101, 23))
self.clearBtn.setObjectName("clearBtn")
self.addBtn = QtWidgets.QPushButton(myfirstgui)
self.addBtn.setGeometry(QtCore.QRect(10, 40, 101, 23))
self.addBtn.setObjectName("addBtn")
self.retranslateUi(myfirstgui)
self.buttonBox.accepted.connect(myfirstgui.accept)
self.buttonBox.rejected.connect(myfirstgui.reject)
self.clearBtn.clicked.connect(self.listWidget.clear)
QtCore.QMetaObject.connectSlotsByName(myfirstgui)
def retranslateUi(self, myfirstgui):
_translate = QtCore.QCoreApplication.translate
myfirstgui.setWindowTitle(_translate("myfirstgui", "My First Gui!"))
self.clearBtn.setText(_translate("myfirstgui", "clear"))
self.addBtn.setText(_translate("myfirstgui", "add"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
myfirstgui = QtWidgets.QDialog()
ui = Ui_myfirstgui()
ui.setupUi(myfirstgui)
myfirstgui.show()
sys.exit(app.exec_())
GUI dynamisch erzeugen
Wollen wir nicht erst Python Code generieren, sondern direkt dynamisch die GUI erzeugen für eine Anwendung die bereits existiert, können wir unsere firstgui.ui
folgendermaßen in unseren Code integrieren:
import sys
from PyQt5.QtWidgets import QApplication, QDialog
from firstgui import Ui_myfirstgui
app = QApplication(sys.argv)
window = QDialog()
ui = Ui_myfirstgui()
ui.setupUi(window)
window.show()
sys.exit(app.exec_())
Das erzeugt ebenfalls die definierte GUI, allerdings ohne dass wir den Code dafür direkt zu Gesicht bekommen. Aber wie funktioniert das? Das klappt weil wir unsere firstgui.ui
importieren:
from firstgui import Ui_myfirstgui
from firstgui
ist hier die .ui
Datei und Ui_myfirstgui
ist die darin definierte Klasse myfirstgui
mit Prefix Ui_
- was eine Konvention zu sein scheint.