PyQt = Python mit Qt

Qt ist ein weit verbreitetes Framework für die Entwicklung von plattformübergreifenden grafischen Benutzeroberflächen (GUIs) . PyQt ist ein Python-Binding für das Qt-Framework und bietet mehr Funktionalitäten als Tkinter.

PyQT muss auf dem System installiert werden. Bei einer Qt-Installation werden für gewöhnlich die Programme Qt Designer, Qt Assistant und Qt Linguist mit installiert. Ersteres ist ein Programm zur komfortablen Gestaltung grafischer Benutzeroberflächen. Qt Assistant ist ein Tool zum Lesen der Qt-Hilfe und Qt Linguist ist ein Hilfsmittel zur Lokalisierung von Qt-Anwendungen .

Der QTDesigner kann über die Shell durch $designer aufgerufen werden:

Mit dem Qt Designer erstellen Sie per Drag-and-drop einfache oder komplexe Layouts. Über das GUI-Toolkit PyQt kann man das erstellte Layout dann für sein Python-Programm nutzen. Dabei werden Aussehen und Logik streng getrennt: Das Design wird in einer extra UI-Datei ausgelagert, die Funktionen dafür erstellt man wie gewohnt in der Python-Datei. PyQt-Kentnisse helfen natürlich, allerdings eignet sich der Designer auch gut, um grundlegende Konzepte von PyQt und beziehungsweise Qt zu lernen.

Module und Widgets

Der Hauptunterschied zwischen Modulen und Widgets in PyQt liegt in ihrer Funktion und Struktur:

Widgets:

  • Widgets sind visuelle Elemente der grafischen Benutzeroberfläche (GUI) in PyQt

Sie sind Klassen, die von QWidget abgeleitet sind und repräsentieren UI-Komponenten wie Buttons, Labels, Textfelder etc. Beispiele für Widgets sind QCheckBox, QSlider, QLabel usw. Widgets können in einer Hierarchie angeordnet werden, wobei ein Widget ein Eltern-Widget (parent) haben kann

Module:

  • Module sind Python-Dateien, die Code organisieren und gruppieren

In PyQt werden verschiedene Funktionalitäten in separate Module aufgeteilt, z.B. QtGui, QtWidgets, QtCore

  • Module enthalten Klassen, Funktionen und Variablen, die thematisch zusammengehören.
  • Sie ermöglichen eine strukturierte und modulare Entwicklung von PyQt-Anwendungen.

Zusammengefasst: Widgets sind die visuellen Bausteine der Benutzeroberfläche, während Module die Codeorganisation und -struktur in PyQt-Anwendungen ermöglichen. Widgets werden typischerweise innerhalb von Modulen definiert und verwendet, um GUIs zu erstellen.

Durch den Befehl

pyuic6 -o typeitin.py typeitin.ui 

Wird die QT-Datei in eine Python Klasse umgewandelt. Die Datei mit der Endung .py ist die Python Datei, die mit der Endung .ui stehen für USERINTERFACE-Dateien. Also für die stylistische Gestaltung. Diese Dateien arbeiten mit XML

Ein einfaches Fenster verursacht einen ausführlichen Code:

zuerst werden die erforderlichen Module importiert:

from PyQt6.QtWidgets import QApplication, QWidget

Für jede PyQt Anwendung muss ein Objekt der Klasse QApplication erstellt werden:

app = QApplication(sys.argv)

Hier wird ein Fenster erzeugt:

w = QWidget()

hier wird w.show genutzt um das Fenster anzuzeigen

w.show()

Was die mainloop Schleife in tkinter ist, ist hier der folgende Befehl:

sys.exit(app.exec_( ) )

Mit diesem wird die Benutzeroberfläche aktiviert.

import sys
from PyQt6.QtWidgets import QApplication, QWidget
if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = QWidget()
    w.resize(300,300)
    w.setWindowTitle("einfaches Fenster mit Python und QT")
    w.show()
    sys.exit(app.exec())

Was Sie sehen, hängt davon ab, auf welcher Plattform Sie dieses Beispiel ausführen. Das Bild unten zeigt das Fenster, wie es unter Windows, macOS und Linux (Ubuntu) angezeigt wird.

Schauen wir uns zunächst einige der gebräuchlichsten PyQt-Widgets an. Der folgende Code erstellt eine Reihe von PyQt-Widgets und fügt sie einem Fensterlayout hinzu, sodass Sie sie zusammen sehen können:

import sys

from PyQt6.QtWidgets import (
    QApplication,
    QCheckBox,
    QComboBox,
    QDateEdit,
    QDateTimeEdit,
    QDial,
    QDoubleSpinBox,
    QFontComboBox,
    QLabel,
    QLCDNumber,
    QLineEdit,
    QMainWindow,
    QProgressBar,
    QPushButton,
    QRadioButton,
    QSlider,
    QSpinBox,
    QTimeEdit,
    QVBoxLayout,
    QWidget,
)

# Subclass QMainWindow to customize your application's main window
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Widgets App")

        layout = QVBoxLayout()
        widgets = [
            QCheckBox,
            QComboBox,
            QDateEdit,
            QDateTimeEdit,
            QDial,
            QDoubleSpinBox,
            QFontComboBox,
            QLCDNumber,
            QLabel,
            QLineEdit,
            QProgressBar,
            QPushButton,
            QRadioButton,
            QSlider,
            QSpinBox,
            QTimeEdit,
        ]

        for w in widgets:
            layout.addWidget(w())

        widget = QWidget()
        widget.setLayout(layout)

        # Set the central widget of the Window. Widget will expand
        # to take up all the space in the window by default.
        self.setCentralWidget(widget)

app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

In Qt finden sich zwei Techniken der ereignisgesteuerten Programmierung: zum einen Events und zum anderen Signale und Slots.

.ui verknüpfen

Die Stylingdatei anrede.ui wird mit der Python Datei verknüpft

import sys
from PyQt6 import QtWidgets, uic

class AnredeDialog(QtWidgets.QDialog):
    def __init__(self):
        super().__init__()
        uic.loadUi("anrede.ui", self)
        self.buttonBox.accepted.connect(self.on_accept)

    def on_accept(self):
        name = self.name.toPlainText()
        if self.frau.isChecked():
            print(f"Sehr geehrte Frau {name}")
        elif self.mann.isChecked():
            print(f"Sehr geehrter Herr {name}")
        else:
            print(f"Sehr geehrte(r) {name}")

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    dialog = AnredeDialog()
    dialog.show()
    sys.exit(app.exec())

Ein Beispiel für eine .ui Datei:
Also als .xml erstellt:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Dialog</class>
 <widget class="QDialog" name="Dialog">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Dialog</string>
  </property>
  <widget class="QDialogButtonBox" name="buttonBox">
   <property name="geometry">
    <rect>
     <x>30</x>
     <y>240</y>
     <width>341</width>
     <height>32</height>
    </rect>
   </property>
   <property name="orientation">
    <enum>Qt::Horizontal</enum>
   </property>
   <property name="standardButtons">
    <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
   </property>
  </widget>
  <widget class="QTextEdit" name="name">
   <property name="geometry">
    <rect>
     <x>130</x>
     <y>30</y>
     <width>221</width>
     <height>31</height>
    </rect>
   </property>
  </widget>
  <widget class="QLabel" name="label">
   <property name="geometry">
    <rect>
     <x>70</x>
     <y>30</y>
     <width>51</width>
     <height>41</height>
    </rect>
   </property>
   <property name="text">
    <string>Name</string>
   </property>
  </widget>
  <widget class="QRadioButton" name="frau">
   <property name="geometry">
    <rect>
     <x>150</x>
     <y>90</y>
     <width>109</width>
     <height>25</height>
    </rect>
   </property>
   <property name="text">
    <string>weiblich</string>
   </property>
  </widget>
  <widget class="QRadioButton" name="mann">
   <property name="geometry">
    <rect>
     <x>150</x>
     <y>130</y>
     <width>109</width>
     <height>25</height>
    </rect>
   </property>
   <property name="text">
    <string>männlich</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections>
  <connection>
   <sender>buttonBox</sender>
   <signal>accepted()</signal>
   <receiver>Dialog</receiver>
   <slot>accept()</slot>
   <hints>
    <hint type="sourcelabel">
     <x>248</x>
     <y>254</y>
    </hint>
    <hint type="destinationlabel">
     <x>157</x>
     <y>274</y>
    </hint>
   </hints>
  </connection>
  <connection>
   <sender>buttonBox</sender>
   <signal>rejected()</signal>
   <receiver>Dialog</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>
 </connections>
</ui>

Ein Label definieren:

label = QLabel(w) wurde festgelegt. In diesem Kontext gibt es kein self, da wir nicht innerhalb einer Klasse sind. Stattdessen verwenden wir w als Elternobjekt für das Label.

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QFrame

if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = QWidget()
    w.resize(300, 300)
    w.setWindowTitle("Bist du voll?")
    
    label = QLabel(w)  #
    label.setFrameStyle(QFrame.Shape.Panel | QFrame.Shadow.Sunken)  
    label.setText("Wann bist du geboren?")
    
    w.show()
    sys.exit(app.exec())

Um die Elemente hinzuzufügen und anzeigen zu lassen müssen die Widgets dem Layout hinzugefügt werden.

Bsp:

layout.addWidget(label)
layout.addWidget(eingabe)

Eine Messagbox erstellen:


import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox
from PyQt6.QtGui import *
from PyQt6.QtCore import *

def showdialog():
    msg = QMessageBox()
    msg.setWindowTitle("Message")
    msg.setText("This is a message!")
    msg.exec()

def window():
    app = QApplication(sys.argv)
    w = QWidget()
    b = QPushButton(w)
    b.setText("Show message!")

    b.move(50,50)
    b.clicked.connect(showdialog)
    w.setWindowTitle("PyQt Dialog demo")
    w.show()
    sys.exit(app.exec())

if __name__ == '__main__': 
    window()

Ein Eingabefeld erstellen

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QFrame, QVBoxLayout, QLineEdit

class SimpleInput(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Erstellen eines vertikalen Layouts
        layout = QVBoxLayout()

        # Erstellen und Hinzufügen des Labels
        label = QLabel(self)
        label.setFrameStyle(QFrame.Shape.Panel | QFrame.Shadow.Sunken)
        label.setText("Wann bist du geboren?")
        layout.addWidget(label)

        # Erstellen eines Eingabefeldes
        self.inputField = QLineEdit()
        
        # Hinzufügen des Eingabefeldes zum Layout
        layout.addWidget(self.inputField)

        # Setzen des Layouts für das Fenster
        self.setLayout(layout)

        # Fenster-Eigenschaften
        self.setGeometry(300, 300, 300, 100)
        self.setWindowTitle('Bist du voll?')
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = SimpleInput()
    sys.exit(app.exec())

Schaltflächen (QPushButton) können zu jedem Fenster hinzugefügt werden. Die Klasse QPushButton hat die Methode setText() für die Beschriftung und move(x,y) für die Position.

Einen ok Button erstellen:

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QFrame, QVBoxLayout, QLineEdit, QPushButton

class SimpleInput(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # Erstellen eines vertikalen Layouts
        layout = QVBoxLayout()

        # Erstellen und Hinzufügen des Labels
        label = QLabel(self)
        label.setFrameStyle(QFrame.Shape.Panel | QFrame.Shadow.Sunken)
        label.setText("Wann bist du geboren?")
        layout.addWidget(label)

        # Erstellen eines Eingabefeldes
        self.inputField = QLineEdit()
        
        # Hinzufügen des Eingabefeldes zum Layout
        layout.addWidget(self.inputField)

        # Erstellen des OK-Buttons
        ok_button = QPushButton('OK', self)
        ok_button.clicked.connect(self.on_click)

        # Hinzufügen des Buttons zum Layout
        layout.addWidget(ok_button)

        # Setzen des Layouts für das Fenster
        self.setLayout(layout)

        # Fenster-Eigenschaften
        self.setGeometry(300, 300, 300, 150)  # Höhe auf 150 erhöht, um Platz für den Button zu schaffen
        self.setWindowTitle('Bist du voll?')

    def on_click(self):
        print('OK-Button wurde geklickt!')
        # Hier können Sie den eingegebenen Text verarbeiten
        print(f'Eingabe: {self.inputField.text()}')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = SimpleInput()
    ex.show()  # Fenster nach der Initialisierung anzeigen
    sys.exit(app.exec())

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QMessageBox

class SimpleInput(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        layout = QVBoxLayout()

        self.label = QLabel("Gib dein Geburtsjahr ein:")
        layout.addWidget(self.label)

        self.inputField = QLineEdit()
        layout.addWidget(self.inputField)

        self.button = QPushButton('Berechnen')
        self.button.clicked.connect(self.on_click)
        layout.addWidget(self.button)

        self.setLayout(layout)
        self.setGeometry(300, 300, 300, 150)
        self.setWindowTitle('Altersrechner')

    def on_click(self):
        try:
            eingabe = self.inputField.text()
            geburtsjahr = int(eingabe)
            alter = 2024 - geburtsjahr
            
            message = f"Du bist {alter} Jahre alt."
            if alter >= 18:
                message += "\nDu bist volljährig."
            else:
                message += "\nDu bist noch nicht volljährig."
            
            QMessageBox.information(self, "Altersberechnung", message)
        except ValueError:
            QMessageBox.warning(self, "Fehler", "Bitte gib ein gültiges Geburtsjahr ein.")

if __name__ == '__main__':
    app = QApplication(sys.argv)
    gebjahr = SimpleInput()
    gebjahr.show()
    sys.exit(app.exec())

Textarea / Textbereich

Ein Textbereich kann in Python PyQt mit dem Widget QPlainTextEdit erstellt werden. QPlainTextEdit ist ein mehrzeiliger Textbereich in PyQt. Um den Text festzulegen, verwenden wir dessen Methode insertPlainText(). Wir können seine Position und Größe mit den Methoden move() und resize() festlegen

Das folgende Beispiel erstellt einen Textbereich QPlainTextEdit mit PyQt5. Sie können dieses Widget von PyQt5.QtWidgets laden.

from PyQt5.QtWidgets import QPlainTextEdit

Sie benötigen außerdem QMainWindow und QWidget

from PyQt5.QtWidgets import QMainWindow, QWidget, QPlainTextEdit

Dann können Sie ein neues Textbereich-Widget wie folgt erstellen:

self.b = QPlainTextEdit(self)

Sie können Text programmgesteuert in den Textbereich einfügen:

self.b.insertPlainText("Hier können Sie Text schreiben.\n")

Stellen Sie seine Position (horizontal, vertikal) innerhalb des Fensters ein:

self.b.move(10,10)

Und ändern Sie es in die Änderung (Breite, Höhe)

self.b.resize(400,200)

QPlainTextEdit-Beispiel

Wir erstellen das übliche QMainWindow, dem wir das Widget hinzufügen. Es ist nur für einfachen Text, wie Notepad. Um neue Zeilen hinzuzufügen, fügen wir das Zeichen \n hinzu Es wurde eine Klasse definiert

from PyQt6.QtWidgets import QApplication, QWidget, QMainWindow, QPlainTextEdit
from PyQt6.QtCore import QSize
import sys

class Fenster(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setMinimumSize(QSize(440, 240))    
        self.setWindowTitle("PyQt6 Textarea") 

        # Add text field
        self.b = QPlainTextEdit(self)
        self.b.insertPlainText("Texteingabe hier.\n")
        self.b.move(10, 10)
        self.b.resize(400, 200)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Fenster()
    ex.show()
    sys.exit(app.exec())

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QFrame, QPushButton, QVBoxLayout

class eingaben:
    def __init__(self, bezeichnung, text_dazu):
        self.bezeichnung = bezeichnung
        self.text_dazu = text_dazu

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setWindowTitle("Typeitin")
        self.resize(200, 800)

        layout = QVBoxLayout()

        # Beispiel für die Verwendung der eingaben-Klasse
        eingabe1 = eingaben("Beispiel", "Dies ist ein Beispieltext")
        label = QLabel(f"{eingabe1.bezeichnung}: {eingabe1.text_dazu}")
        layout.addWidget(label)

        # Erstellen des OK-Buttons
        ok_button = QPushButton('OK', self)
        ok_button.clicked.connect(self.on_click)

        # Hinzufügen des Buttons zum Layout
        layout.addWidget(ok_button)

        self.setLayout(layout)

    def on_click(self):
        print("OK-Button wurde geklickt")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

In die Zwischenablage kopieren:

QClipboard ist eine Klasse in PyQt, die den Zugriff auf die Zwischenablage des Systems ermöglicht. Hier sind die wichtigsten Punkte zu QClipboard:

  1. Funktionalität:
    • QClipboard ermöglicht das Lesen und Schreiben von Daten in die Systemzwischenablage.
    • Es unterstützt verschiedene Datentypen wie Text, Bilder und benutzerdefinierte MIME-Typen.
  2. Zugriff:
    • Man erhält eine Instanz von QClipboard über die QApplication: pythonclipboard = QApplication.clipboard()

Hauptmethoden:

image(): Gibt das Bild aus der Zwischenablage zurück.

setText(text): Kopiert Text in die Zwischenablage.

text(): Gibt den Text aus der Zwischenablage zurück.

setImage(image): Kopiert ein Bild in die Zwischenablage.

clipboard = QApplication.clipboard()
clipboard.setText("Dieser Text ist jetzt in der Zwischenablage")
from PyQt6.QtWidgets import QApplication, QDialog, QPushButton, QVBoxLayout

class CustomDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Mein Dialog")

        layout = QVBoxLayout()
        button = QPushButton("Schließen")
        button.clicked.connect(self.accept)
        layout.addWidget(button)

        self.setLayout(layout)

if __name__ == '__main__':
    app = QApplication([])
    dialog = CustomDialog()
    dialog.exec()
from PyQt6.QtWidgets import QApplication, QDialog, QPushButton, QVBoxLayout

class CustomDialog(QDialog):
def init(self, parent=None):
super().init(parent)
self.setWindowTitle("Mein Dialog")
self.setGeometry(100, 100, 200, 600) # x, y, Breite, Höhe

    layout = QVBoxLayout()

    button = QPushButton("Schließen")
    button.clicked.connect(self.close)
    layout.addWidget(button)

    button1 = QPushButton("SgDuH")
    button1.setText("SgDuH")
    layout.addWidget(button1)  # Fügen Sie button1 zum Layout hinzu

    self.setLayout(layout)

if name == 'main':
     app = QApplication([])
     dialog = CustomDialog()
     dialog.exec()