[[Vorlage(archiviert)]] {{{#!vorlage Wissen [:Terminal:Ein Terminal öffnen] [:Programme kompilieren:Pakete aus dem Quellcode erstellen] [:Qt_Creator:QtCreator (optional)] }}} [[Inhaltsverzeichnis(3)]] 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. {{{#!code cpp ifndef AUSGABE_H #define AUSGABE_H #include 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=== {{{#!code cpp #include "ausgabe.h" #include //______________________________________________________________________________ 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== {{{#!vorlage Hinweis Um eine Verbindung ohne Objektinstanz zu ermöglichen, kann das statische `QObject::connect` verwendet werden. }}} {{{#!code cpp #include #include #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: {{{#!code bash 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: {{{#!vorlage Befehl qmake -project }}} Resultat: {{{#!code bash ###################################################################### # 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 {{{#!vorlage befehl 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. {{{#!vorlage 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== {{{#!code cpp #include #include 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. {{{ main.qml }}} == Kompilierung == Für das folgende Beispiel werden zusätzliche Pakete benötigt: {{{#!vorlage Paketinstallation qtdeclarative5-dev }}} Es gelten die gleichen Regeln, wie im C++-Beispiel, daher wird hier die gekürzte Ausgabe verwendet: {{{#!code bash 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: {{{#!vorlage befehl qmake -project QT+=quick . }}} Anschliessend wird wieder `qmake && make` verwendet. =Python / PySide= Zusätzlich nötige Pakete für dieses Beispiel: {{{#!vorlage Paketinstallation python3-pyside2.qtcore, universe/python python3-pyside2.qtwidgets, universe/python }}} Ein einfaches Beispiel unter Verwendung von PySide2. Als Projektname wurde ''AusgabePython.py'' gewählt: {{{#!code python #!/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: {{{#!code bash { "files": ["AusgabePython.py"] } }}} =Links= * [:Qt5:] Hauptartikel # tag: Qt