Beispiele
Archivierte Anleitung
Dieser Artikel wurde archiviert. Das bedeutet, dass er nicht mehr auf Richtigkeit überprüft oder anderweitig gepflegt wird. Der Inhalt wurde für keine aktuell unterstützte Ubuntu-Version getestet. Wenn du Gründe für eine Wiederherstellung siehst, melde dich bitte in der Diskussion zum Artikel. Bis dahin bleibt die Seite für weitere Änderungen gesperrt.
Zum Verständnis dieses Artikels sind folgende Seiten hilfreich:
Dies sind die Beispiele zum Hauptartikel Qt5. QCoreApplication zeigt ein einfaches Signal&Slot-Beispiel, QML ein einfaches Layout im „Hello World“-Stil mit einer separaten Schaltfläche zum Beenden. Ein PySide-Beispiel zeigt die simple Verwendung eines Labels.
QCoreApplication C++¶
Dieses Beispiel zeigt die Verwendung des Signal&Slot-Konzeptes, so wie die Handhabung der Meldungen mit den Qt-eigenen Methoden über QDebug in einer schlichten Konsolenanwendung.
Klasse Ausgabe¶
ausgabe.h¶
Es wird das Q_OBJECT-Makro verwendet, um die Klasse dem Qt-Objekt-System bekannt zu machen. Eine solche Klasse muss von QObject oder einer Kindklasse abgeleitet werden, um das Signal&Slot-Konzept verwenden zu können.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ifndef AUSGABE_H #define AUSGABE_H #include <QObject> class Ausgabe : public QObject { Q_OBJECT public: Ausgabe( QObject *parent = nullptr ); public slots: void los(); // eigenen Slot definieren signals: void fertig(); // Eigenes Signal ohne Argumente }; #endif // AUSGABE_H |
ausgabe.cpp¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #include "ausgabe.h" #include <QDebug> //______________________________________________________________________________ Ausgabe::Ausgabe( QObject *parent ) : QObject( parent ) { } //______________________________________________________________________________ // Unser Slot wird als normale C++-Funktion implementiert: void Ausgabe::los() { qDebug() << "Debug-Nachricht"; qInfo() << "Hallo Welt!"; qCritical() << "Fehlermeldung!"; emit fertig(); // Signal senden } //______________________________________________________________________________ // Das Signal wird nicht implementiert! |
main.cpp¶
Hinweis:
Um eine Verbindung ohne Objektinstanz zu ermöglichen, kann das statische QObject::connect
verwendet werden.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include <QtCore> #include <QDebug> #include "ausgabe.h" int main( int argc, char **argv ) { QCoreApplication a( argc, argv ); // Initialisierung des „main event loops“ qDebug() << "Initialisiere Ausgabe…"; // Die Klasse Ausgabe wird als Kind der CoreApplication auf dem Heap initialisiert, // so dass die Instanz beim Beenden automatisch gelöscht wird. Ausgabe *ausgabe = new Ausgabe( &a ); // Signale und Slots: Verbinden der quit()-Methode mit der Klasse // Der main loop wird verlassen und das Programm beendet, sobald // das Signal „fertig“ empfangen wird. quit() ist ein Standard-Slot a.connect( ausgabe, &Ausgabe::fertig, &a, &QCoreApplication::quit ); // Alternative Schreibweise mit Makros: a.connect( ausgabe, SIGNAL( fertig() ), &a, SLOT( quit() ) ); // Man kann die Slot-Methoden auch ohne Verbindung ähnlich eines callbacks // verwenden: QTimer::singleShot( 0, ausgabe , SLOT( los() ) ); return a.exec(); // Mit Exit-Code der CoreApplication beenden } |
Kompilieren¶
ausgabe.pro¶
Erstellt man die Datei mit dem QtCreator, sieht diese etwa so aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | QT -= gui CONFIG += c++11 console CONFIG -= app_bundle # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ ausgabe.cpp \ main.cpp # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target HEADERS += \ ausgabe.h |
Die Projektdatei kann aber auch per qmake
automatisch generiert werden:
qmake -project
Resultat:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ###################################################################### # Automatically generated by qmake (3.1) Mon Dec 7 16:53:24 2020 ###################################################################### TEMPLATE = app TARGET = Ausgabe INCLUDEPATH += . # You can make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # Please consult the documentation of the deprecated API in order to know # how to port your code away from it. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 # Input HEADERS += ausgabe.h SOURCES += ausgabe.cpp main.cpp |
Anschließend kann das Projekt mit
qmake && make
kompiliert werden.
Ausführung¶
Wird das Programm im Terminal ausgeführt, so erhält man die Ausgaben
Initialisiere Ausgabe… Debug-Nachricht Hallo Welt! Fehlermeldung!
Beim grafischen Start — bspw. per .desktop-Datei oder im QtCreator — erhält man keine sichtbare Ausgabe. Da Qt so konzipiert ist, dass solche Nachrichten nicht verloren gehen, werden die Meldungen entsprechend ihrer Art an das Betriebssystem weitergegeben. journalctl -xe
sieht dann bspw. wie folgt aus:
Dec 07 16:56:54 desktop Ausgabe[6838]: Initialisiere Ausgabe… Dec 07 16:56:54 desktop Ausgabe[6838]: Debug-Nachricht Dec 07 16:56:54 desktop Ausgabe[6838]: Hallo Welt! Dec 07 16:56:54 desktop Ausgabe[6838]: Fehlermeldung!
Di Die Ausgabe im System erfolgt farbig, je nach Typ der Meldung, dies ist hier nicht dargestellt.
Hinweis:
Um die Ausgaben bei einer GUI-Anwendung im Terminal zu sehen, kann die Option CONFIG += console
in der Projektdatei verwendet werden.
QtQuick/QML¶
Mit Hilfe von QtQuick lassen sich recht schnell Benutzeroberflächen erstellen. Es gibt mehrere Möglichkeiten mit QML zu Arbeiten, hier soll ein einfaches „Hello-World“-Beispiel in QtQuick reichen.
main.cpp¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <QGuiApplication> #include <QQmlApplicationEngine> int main(int argc, char *argv[]) { // Unterstützung für hochauflösende Geräte: QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // Der „main event loop“ QGuiApplication app(argc, argv); // die QML-Engine bietet die Grundlagen für die Darstellung mittels QML // Beim Kompilieren wird der QML-Code zu C++ übersetzt QQmlApplicationEngine engine; // Die QML-Datei wird per Ressource eingebunden. Das erlaubt das einkompilieren. // Wäre die Angabe per file://, würde lediglich die Engine einkompiliert und die // QML-Dateien zur Laufzeit auswerten const QUrl url(QStringLiteral("qrc:/main.qml")); // Verbindung der Signale, inkl. Fehlerbehandlung // Dies stellt sicher, dass die Engine die Anwendung mit Fehler beendet, // wenn die QMLEngine die Datei nicht laden/finden/verarbeiten kann QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); // laden der main.qml return app.exec(); // Ergebnis des main loops } |
main.qml¶
import QtQuick 2.12 import QtQuick.Window 2.12 // Window import QtQuick.Controls 2.0 // Button Window { width: row.width height: ende.height visible: true title: "ubuntuusers.de" Row{ id: row height: ende.height Text { padding: font.pointSize text: "Hallo QML!" } Button { id: ende text: "Ende" onReleased: Qt.quit() } } }
qml.qrc¶
Eine Ressource-Datei ist eine XML-Datei, die entsprechende Verweise auf einzubettende Elemente liefert. So können bspw. auch das Anwendungs-Icon oder SQL-Routinen in die ausführbare Datei einkompiliert werden und müssen nicht im Zielsystem in Ordner einsortiert werden oder gegen Manipulation geschützt.
<RCC> <qresource prefix="/"> <file>main.qml</file> </qresource> </RCC>
Kompilierung¶
Für das folgende Beispiel werden zusätzliche Pakete benötigt:
qtdeclarative5-dev
Befehl zum Installieren der Pakete:
sudo apt-get install qtdeclarative5-dev
Oder mit apturl installieren, Link: apt://qtdeclarative5-dev
Es gelten die gleichen Regeln, wie im C++-Beispiel, daher wird hier die gekürzte Ausgabe verwendet:
1 2 3 4 5 6 | QT += quick TEMPLATE = app TARGET = AusgabeQML INCLUDEPATH += . SOURCES += main.cpp qml RESOURCES += qml.qrc |
Wichtig ist die Resource-Datei als solche zu kennzeichnen, damit das Einkompilieren funktioniert, so wie die Option für QtQuick zu setzen. Das generieren der Projektdatei funktioniert mit folgendem Aufruf:
qmake -project QT+=quick .
Anschliessend wird wieder qmake && make
verwendet.
Python / PySide¶
Zusätzlich nötige Pakete für dieses Beispiel:
python3-pyside2.qtcore (universe/python)
python3-pyside2.qtwidgets (universe/python)
Befehl zum Installieren der Pakete:
sudo apt-get install python3-pyside2.qtcore python3-pyside2.qtwidgets
Oder mit apturl installieren, Link: apt://python3-pyside2.qtcore,python3-pyside2.qtwidgets
Ein einfaches Beispiel unter Verwendung von PySide2. Als Projektname wurde AusgabePython.py gewählt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/usr/bin/python3 import sys from PySide2.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout class AusgabePython(QWidget): def __init__(self): QWidget.__init__(self) label = QLabel(self) label.setText('ubuntuusers.de sagt:\n\t"Hallo Python!"') lay = QVBoxLayout() lay.addWidget(label) self.setLayout(lay) if __name__ == "__main__": app = QApplication([]) window = AusgabePython() window.show() sys.exit(app.exec_()) |
Projektdatei¶
Eine Projektdatei wird bei Python nicht benötigt. Im Vergleich zu den C++-Ansätzen listet diese unter Verwendung des QtCreators nur enthaltene Dateien auf:
1 2 3 | { "files": ["AusgabePython.py"] } |
Links¶
Qt5 Hauptartikel