ubuntuusers.de

🛈 Aktuell gibt es im Wiki ca. 300 Artikel, die nur für Xenial getestet sind. Dies entspricht ca. 3,8 % aller Wikiartikel. Damit diese im Frühjahr nicht alle archiviert werden müssen, ist eure Mithilfe gefragt!

Beispiele

Dieser Artikel wurde für die folgenden Ubuntu-Versionen getestet:


Du möchtest den Artikel für eine weitere Ubuntu-Version testen? Mitarbeit im Wiki ist immer willkommen! Dazu sind die Hinweise zum Testen von Artikeln zu beachten.

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

Paketliste zum Kopieren:

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)

Paketliste zum Kopieren:

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"]
}

  • Qt5 Hauptartikel

Diese Revision wurde am 10. Januar 2021 00:19 von ubot erstellt.
Die folgenden Schlagworte wurden dem Artikel zugewiesen: Qt