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.

Quelle

Kommentare unterstützt von Disqus.

Nächster Beitrag Vorheriger Beitrag