Liebe Leserinnen, liebe Leser,

in diesem Beitrag teile ich meine erste Eindrücke über das plattformunabhängige Framework Qt, die anscheinend auf Linux (auch eingebettet), Windows, macOS, iOS, Android, QNX, Integrity, VxWorks, usw. eingesetzt werden kann. Interessanterweise befinden sich in dieser Liste ausschließlich eigebettete Systeme auch. Um eine Übersicht über das Framework zu bekommen, habe ich einige Beispielanwendungen mit verschiedenen Widgets gemacht. Bevor diese Anwendungen geschaut werden können, soll die Arbeitsumgebung und das Buildwerkzeug angeschaut werden.

Ich habe Qt Creator und qmake für die Erstellung von kleinen Anwendungen als eine Abkürzung verwendet, sodass ich nicht alles manuell machen brauche. Zugegeben, ich wollte mich an CMake halten, weil ich es früher für meine andere Lernprojekte beutzt habe, und weil Qt Creator es unterstüzt. Nachdem ich CMake mit Qt Creator ausprobiert habe, wurde es deutlich, dass die Unterstüztung von CMake nicht so fortgeschritten als die Unterstüztung von qmake ist (das ist nicht erstaunlich). Als das früher erwähnt wurde, habe ich mich für die Nutzung von qmake entschieden. Sowieso, um die Nutzung von CMake mit Qt zu lernen, habe ich ein Qt Hello World Projekt mit CMake und qmake gemacht. Das war auch eine Gelegenheit, um den Unterschied zwischen qmake und CMake zu betrachten. Das unten zu sehende erste Beispiel ist eine CMakeLists.txt Datei, die ich selbst geschrieben habe, und die andere ist eine HelloWorld.pro Datei, die Qt Creator erzeugt hat und von mir (mit Buildflaggen und C++ Standard) ein bisschen ergänzt wurde. Auf diese Weise sind beide aus dem Gesichtspunkt der Ergebnisse gleichwertig:

CMake

cmake_minimum_required (VERSION 3.9 FATAL_ERROR)

project (QtHelloWorld CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED 14)

set(CMAKE_CXX_FLAGS "-g -Og ${CMAKE_CXX_FLAGS}")

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

# Note, that this command exists only since CMake 3.12 (current)
# add_definitions(-DQT_DEPRECATED_WARNINGS) was the way to go earlier
add_compile_definitions(QT_DEPRECATED_WARNINGS)

find_package(Qt5 COMPONENTS Core Widgets REQUIRED)

set(SOURCES
    main.cpp
    window.cpp
    myres.qrc)

add_executable(QtHelloWorld ${SOURCES})
target_link_libraries(QtHelloWorld Qt5::Widgets)

qmake

CONFIG += c++14
QMAKE_CXXFLAGS_DEBUG += -g -Og

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = QtHelloWorld
TEMPLATE = app

DEFINES += QT_DEPRECATED_WARNINGS

SOURCES += \
        main.cpp \
        window.cpp

HEADERS += \
        window.h

FORMS += \
        window.ui
        
RESOURCES += \
        myres.qrc

Ein aufmerksamer Leser könnte es schon bemerken, dass die CMake Datei keine HEADERS und FORMS Listen hat, und RESOURCES hat sich mit SOURCES fusioniert. Das passierte, weil CMake nimmt die Existenz von Header-Dateien und ui-Dateien (mit entsprechenden Namen und #include) an, und daher braucht man diese Dateien nicht erwähnen. Sie werden erst im Falle erwähnt, wenn CMAKE_AUTOMOC, CMAKE_AUTOUIC and CMAKE_AUTORCC mit ON eingeschaltet sind. Als es früher dennoch erwähnt wurde, habe ich mich an qmake gehalten. Ich habe zufällige Prüfungen mit der CMake-Datei auch gemacht, und alles wurde damit erwartungsgemäß kompiliert, angenommen, dass COMPONENTS und SOURCES entsprechend angepasst wurden. Eine gute Lektüre an der Nutzung von CMake mit Qt ist in der entsprechenden documentation zu finden.

Hier gibt’s einige sehr einfache Qt-Anwendungen, die ich mithilfe der obengenannten Werzeuge und online Anleitungen gemacht habe. Das bedeutet, dass diese Beispiele nicht original sind.

nameEin einfacher Bildbetrachter, der in der Lage ist, Bilder mithilfe eines Dialogs zu eröffnen, und es hat einfache Zoom-Funktionen (Das Bild ist ein Bildschirmausdruck aus einer ‘Stargate: Atlantis’ Episode)


nameEine sehr einfache grafische Oberfläche für ffmpeg


nameEin paar bearbeitbare grafische Primitive


nameEin mini ‘Dateimanager’. Es kann Ornder an dem geeigneten Pfad erstellen und entfernen


nameAbhängig von der ausgewählten Einstellung wird ein Fenster mit unterschiedlicher Implementierung erscheinen.

Die Tatsache, dass einfache Anwendungen mit relativer Leichtigkeit erstellt werden könnten, sagt viel über das Framework, die ich für etwas ganz Übergreifendes halte. So übergreifend, dass das einen Stellvertreter für die meisten Teile der C++ Standardbibliothek hat, wie z.B. Containers, Concurrency, Datenströme, usw. Weiterhin hat das eine eigene einzigartige Funktion für die Weitergabe der Information zwischen Objekten, nämlich der Signal-Slot-Mechanismus, der den Observer-Pattern und Callbacks ersetzt. Das ist funcktioniert dank der etlichen besonderen Makros, die gemäß der offiziellen Dokumentation “von dem Preprozessor erweitert werden, um einige Klassenfuktionen zu definieren. Die Definitionen werden endlich von dem MOC implementiert werden”. MOC bedeutet Meta-Object Compiler. Ein neugieriger Leser könnte schon an dieser Stelle die folgende Frage stellen: was ist CMAKE_AUTOMOC in der CMake-Datei? Einfach gesagt schaltet es MOC ein.

Ein anderes Phänomen, das ich bemerkt habe, war der Versuch, die direkte Nutzung von C++ für GUI-bezogene Aufgaben zu vermeiden. Das wird entweder durch die Nutzung von .ui-Dateien (die tatsächlich XML-Dateien sind), oder durch einen deklarativen Ansatz mit QML2 erreicht. Offensichtlich machen solche Werzeuge die Erstellung von GUI einfacher, und deswegen verstehe ich die Entscheidung von Qt über diese Frage. Interessanter ist, dass nur die direkte Nutzung von C++ ist vermieden, aber die inderekte Nutzung nicht. Als es schon in dem Absatz über Buildwerkzeuge erwähnt wurde, muss man in der CMake-Datei einige Einstellungen (z.B. CMAKE_AUTOUIC) einschalten, die nichts anderes als Werkzeuge für Codeerzeugung sind. Nachdem ich die Projektverzeichnis durchgesucht habe, habe ich die entsprechenden .cpp-Dateien gefunden, also diese Werzeuge scheinen (mir) eine Abstraktionsebene zu sein, und sie werden für die Abstraktion einer ganzen Programmierungssprache verwendet. Toll.

Das ist alles, das ich schreiben wollte, deshalb ist es an der Zeit, diesen Beitrag zu beenden. Natürlich habe ich Qt nicht ernshaft genug verwendet, um eine gegründete Meinung zu haben, aber ich bin beeindruckt. Hoffentlich werde ich mich in der Zukunft in dieses Framework tiefer vertiefen können.

Vielen Dank fürs Lesen.