Qt für macOS - Spezifische Probleme

Diese Seite umreißt die wichtigsten Fragen zur macOS-Unterstützung in Qt. macOS-Terminologien und spezifische Prozesse finden Sie unter https://developer.apple.com/.

Aqua

Der Aqua-Stil ist ein wesentlicher Bestandteil der macOS-Plattform. Wie bei Cocoa bietet Qt Widgets, die wie die in den macOS Human Interface Guidelines beschriebenen aussehen. Beachten Sie, dass Qt Widgets zwar unter der Haube AppKit für das Aussehen verwenden, aber nicht jedes einzelne Qt Widget als umhülltes natives Steuerelement darstellen.

Die Seite Qt Widget Gallery enthält Beispielbilder von Anwendungen, die das macOS Plattformthema verwenden.

Qt-Attribute für macOS

Die folgende Liste enthält eine Reihe nützlicher Attribute, die zur Optimierung von Anwendungen unter macOS verwendet werden können:

macOS puffert den Bildschirm immer doppelt, daher hat das Attribut Qt::WA_PaintOnScreen keine Wirkung. Außerdem ist es unmöglich, außerhalb eines Malereignisses zu malen, daher hat Qt::WA_PaintOutsidePaintEvent ebenfalls keine Wirkung.

Rechte Mausklicks

Die Klasse QContextMenuEvent bietet Unterstützung für den rechten Mausklick für macOS-Anwendungen. Dies wird auf ein Kontextmenü-Ereignis abgebildet, zum Beispiel ein Menü, das eine Popup-Auswahl anzeigt. Dies ist die häufigste Verwendung von rechten Mausklicks und entspricht einem Kontrollklick mit der macOS-Mausunterstützung für eine Taste.

Internationalisierung

Programme unter macOS deklarieren ihre unterstützten Sprachen als Teil der Info.plist des Programms. Das System gleicht dann die unterstützten Sprachen des Programms mit den Spracheinstellungen des Benutzers ab, um das Gebietsschema zu bestimmen, in dem das Programm gestartet wird. Dies wiederum bestimmt die geordneten Sprachen, die durch QLocale::uiLanguages() widergespiegelt werden, und wie System-Frameworks wie AppKit ihre lokalisierten Ressourcen, wie Menütitel und Strings, aufnehmen.

Da Qt-Applikationen nicht von Haus aus übersetzt werden, setzt die standardmäßig generierte Info.plist für CMake und qmake Projekte CFBundleAllowMixedLocalizations auf YES gesetzt, damit System-Frameworks die Lokalisierung auswählen können, die am besten zu den Spracheinstellungen des Benutzers passt, auch wenn diese Lokalisierung für die Anwendung selbst nicht verfügbar ist. Sobald Sie Übersetzungen zu Ihrer Anwendung mittels qt_add_translations hinzufügen, wird der CFBundleAllowMixedLocalizations Schlüssel automatisch entfernt und ersetzt durch CFBundleLocalizationsersetzt, der alle von Ihnen unterstützten Sprachen auflistet. Für qmake muss dieser Prozess manuell durchgeführt werden.

Qt erkennt Menüleisten und wandelt sie in Mac-native Menüleisten um. Die Anpassung an bestehende Qt-Anwendungen erfolgt normalerweise automatisch. Wenn Sie jedoch spezielle Anforderungen haben, wählt die Qt-Implementierung derzeit eine Menüleiste aus, indem sie mit dem aktiven Fenster beginnt (z. B. QGuiApplication::focusWindow()) und die folgenden Tests durchführt:

  1. Wenn das Fenster ein QMenuBar hat, dann wird es verwendet.
  2. Wenn das Fenster modal ist, dann wird seine Menüleiste verwendet. Wenn keine Menüleiste angegeben ist, wird eine Standard-Menüleiste verwendet (wie unten dokumentiert).
  3. Wenn das Fenster kein übergeordnetes Element hat, wird die Standard-Menüleiste verwendet (wie unten beschrieben).

Diese Tests werden in der gesamten Kette der übergeordneten Fenster durchgeführt, bis eine der oben genannten Regeln erfüllt ist. Wenn alles andere fehlschlägt, wird eine Standard-Menüleiste erstellt. Die Standard-Menüleiste von Qt ist eine leere Menüleiste. Sie können jedoch eine andere Standard-Menüleiste erstellen, indem Sie eine übergeordnete Menüleiste QMenuBar erstellen. Die erste erstellte Menüleiste wird als Standardmenüleiste bezeichnet und wird immer dann verwendet, wenn eine Standardmenüleiste benötigt wird.

Die Verwendung von nativen Menüleisten bringt gewisse Einschränkungen für Qt-Klassen mit sich. Der Abschnitt mit der Liste der Einschränkungen unten enthält weitere Informationen.

Qt bietet Unterstützung für die globale Menüleiste mit QMenuBar. macOS-Benutzer erwarten eine Menüleiste am oberen Rand des Bildschirms und Qt berücksichtigt dies.

Außerdem erwarten die Benutzer, dass bestimmte Konventionen eingehalten werden, z.B. sollte das Anwendungsmenü About, Preferences, Quit, usw. enthalten. Qt erfüllt diese Konventionen, obwohl es keine Möglichkeit bietet, direkt mit dem Anwendungsmenü zu interagieren.

Jede QAction hat eine menuRole Eigenschaft, die die spezielle Platzierung von Anwendungsmenüeinträgen steuert; standardmäßig ist menuRole jedoch TextHeuristicRole, was bedeutet, dass die Menüeinträge automatisch durch ihre text erkannt werden.

Andere Standardmenüpunkte wie Ausschneiden, Kopieren, Einfügen und Alles auswählen sind sowohl in Ihrer Anwendung als auch in einigen systemeigenen Dialogen wie QFileDialog anwendbar. Es ist wichtig, dass Sie diese Menüpunkte mit den Standardkurzbefehlen erstellen, damit die entsprechenden Bearbeitungsfunktionen in den Dialogen aktiviert werden. Zur Zeit gibt es keine MenuRole Bezeichner für diese Menüpunkte, aber sie werden automatisch erkannt, genau wie die Menüpunkte der Anwendung, wenn QAction die Standardeinstellung TextHeuristicRole hat.

Sondertasten

Um das erwartete Verhalten für Qt-Anwendungen unter macOS zu gewährleisten, entsprechen die Enum-Werte Qt::Key_Meta, Qt::MetaModifier und Qt::META den Steuerungstasten auf der Standard-Apple-Tastatur und die Enum-Werte Qt::Key_Control, Qt::ControlModifier und Qt::CTRL den Befehlstasten.

Dock

Interaktion mit dem Dock ist möglich. Das Icon kann durch den Aufruf von QWindow::setWindowIcon() aus dem Hauptfenster in Ihrer Anwendung gesetzt werden. Der setWindowIcon()-Aufruf kann so oft wie nötig erfolgen, so dass das Symbol leicht aktualisiert werden kann.

Zugänglichkeit

Viele Benutzer interagieren mit macOS über Hilfsmittel. Das Ziel von Qt ist es, dies in Ihrer Anwendung automatisch zu machen, so dass sie der akzeptierten Praxis auf ihrer Plattform entspricht. Qt nutzt das Zugänglichkeits-Framework von Apple, um Benutzern mit Behinderungen den Zugang zu ermöglichen.

Unterstützung für Bibliotheken und Deployment

Qt bietet Unterstützung für macOS-Strukturen wie Frameworks und Bundles. Es ist wichtig, sich dieser Strukturen bewusst zu sein, da sie sich direkt auf die Bereitstellung von Anwendungen auswirken.

Qt bietet ein Deployment-Tool, macdeployqt, um den Deployment-Prozess zu vereinfachen. Der Artikel Qt für macOS - Deployment behandelt den Deployment-Prozess im Detail.

Qt-Bibliotheken als Frameworks

Standardmäßig wird Qt als ein Satz von Frameworks erstellt. Frameworks sind die von macOS bevorzugte Art der Verteilung von Bibliotheken. Die Apple's Framework Programming Guide Seite hat weit mehr Informationen über Frameworks.

Es ist wichtig, daran zu denken, dass Frameworks immer mit Release-Versionen von Bibliotheken verknüpft werden. Wenn die Debug-Version eines Qt-Frameworks gewünscht ist, verwenden Sie die DYLD_IMAGE_SUFFIX Umgebungsvariablen, um sicherzustellen, dass die Debug-Version geladen wird:

export DYLD_IMAGE_SUFFIX=_debug

Alternativ können Sie Ihre Debug- und Release-Versionen vorübergehend austauschen, was in der technischen Notiz "Debugging Magic" von Apple dokumentiert ist.

Wenn Sie keine Frameworks verwenden möchten, konfigurieren Sie Qt einfach mit -no-framework.

./configure -no-framework

Bündel-basierte Bibliotheken

Wenn Sie einige dynamische Bibliotheken im macOS-Anwendungsbündel (dem Anwendungsverzeichnis) verwenden möchten, erstellen Sie ein Unterverzeichnis namens Frameworks im Anwendungsbündelverzeichnis und platzieren Sie Ihre dynamischen Bibliotheken dort. Die Anwendung wird eine dynamische Bibliothek finden, wenn sie den Installationsnamen @executable_path/../Frameworks/libname.dylib hat.

Wenn Sie qmake und Makefiles verwenden, benutzen Sie die Einstellung QMAKE_LFLAGS_SONAME:

QMAKE_LFLAGS_SONAME  = -Wl,-install_name,@executable_path/../Frameworks/

Alternativ können Sie den Installationsnamen auch mit install_name_tool(1) in der Befehlszeile ändern.

Die Umgebungsvariable DYLD_LIBRARY_PATH setzt diese Einstellungen und alle anderen Standardpfade außer Kraft, wie z. B. die Suche nach dynamischen Bibliotheken in /usr/lib und ähnlichen Standardpfaden.

Kombinieren von Bibliotheken

Wenn Sie eine neue dynamische Bibliothek erstellen wollen, die die dynamischen Qt-Bibliotheken kombiniert, müssen Sie das ld -r Flag einführen. Dann werden in der Ausgabedatei Informationen zur Verschiebung gespeichert, so dass diese Datei Gegenstand eines weiteren ld Laufs sein kann. Dies geschieht durch Setzen des Flags -r in der Datei .pro und den Einstellungen von LFLAGS.

Reihenfolge der Initialisierung

dyld(1) ruft globale statische Initialisierungen in der Reihenfolge auf, in der sie in die Anwendung gelinkt werden. Wenn eine Bibliothek gegen Qt gelinkt wird und die Globals in Qt referenziert (von globalen Initialisierungen in Ihrer eigenen Bibliothek), linken Sie die Anwendung gegen Qt, bevor Sie sie gegen die Bibliothek linken. Andernfalls wird das Ergebnis undefiniert sein, da die globalen Initialisierungen von Qt noch nicht aufgerufen wurden.

Kompilierzeit-Flags

Die folgenden Flags sind hilfreich, wenn Sie macOS-spezifischen Code definieren wollen:

  • Q_OS_DARWIN wird definiert, wenn Qt erkennt, dass Sie sich auf einem Darwin-basierten System wie macOS oder iOS befinden.
  • Q_OS_MACOS ist definiert, wenn Sie sich auf einem macOS-System befinden.

Hinweis: Q_WS_MAC ist in Qt 5 und höher nicht mehr definiert.

Wenn Sie Code für bestimmte Versionen von macOS definieren möchten, verwenden Sie die Verfügbarkeitsmakros, die in /usr/include/AvailabilityMacros.h definiert sind.

Die Dokumentationen QSysInfo und QOperatingSystemVerison enthalten Informationen über die Überprüfung von Laufzeitversionen.

macOS Native API Zugriff

Zugriff auf den Bundle-Pfad

macOS-Programme sind als Verzeichnis strukturiert (mit der Endung .app). Dieses Verzeichnis enthält Unterverzeichnisse und Dateien. Es kann sinnvoll sein, Elemente wie Plugins und Online-Dokumentation innerhalb dieses Bündels zu platzieren. Der folgende Code gibt den Pfad des Anwendungsbündels zurück:

#ifdef Q_OS_MAC   QString bundlePath = QString::fromNSString(NSBundle.mainBundle.bundlePath);    qDebug() << "Bundle path =" << bundlePath;
#endif

Weitere Informationen zur Verwendung der NSBundle-API finden Sie auf der Apple Developer Website.

QCoreApplication::applicationDirPath() kann verwendet werden, um den Pfad der Binärdatei innerhalb des Bundles zu ermitteln.

Verwendung nativer Cocoa-Panels

Der Event-Dispatcher von Qt ist flexibler als das, was Cocoa bietet, und ermöglicht es dem Benutzer, den Event-Dispatcher (und die Ausführung von QEventLoop::exec) zu drehen, ohne darüber nachdenken zu müssen, ob modale Dialoge auf dem Bildschirm angezeigt werden oder nicht (was ein Unterschied zu Cocoa ist). Daher müssen wir in Qt eine zusätzliche Verwaltung vornehmen, um dies korrekt zu handhaben, was das Mischen nativer Panels leider schwierig macht. Der beste Weg, dies zu tun, ist im Moment, dem unten stehenden Muster zu folgen, bei dem wir den Aufruf der Funktion mit nativem Code posten, anstatt sie direkt aufzurufen. Dann wissen wir, dass Qt alle anstehenden Ereignisschleifen-Rekursionen sauber aktualisiert hat, bevor das native Panel angezeigt wird:

#include <QtGui>

class NativeProxyObject : public QObject
{
    Q_OBJECT
public slots:
    void execNativeDialogLater()
    {
        QMetaObject::invokeMethod(this, "execNativeDialogNow", Qt::QueuedConnection);
    }

    void execNativeDialogNow()
    {
        NSRunAlertPanel(@"A Native dialog", @"", @"OK", @"", @"");
    }

};

#include "main.moc"

int main(int argc, char **argv){
    QApplication app(argc, argv);
    NativeProxyObject proxy;
    QPushButton button("Show native dialog");
    QObject::connect(&button, SIGNAL(clicked()), &proxy, SLOT(execNativeDialogLater()));
    button.show();
    return app.exec();
}

Begrenzungen

MySQL und macOS

Es scheint ein Problem zu geben, wenn sowohl -prebind als auch -multi_module definiert sind, wenn statische C-Bibliotheken in dynamische Bibliotheken gelinkt werden. Wenn Sie die folgende Fehlermeldung beim Linken von Qt:

ld: common symbols not allowed with MH_DYLIB output format with the -multi_module option
/usr/local/mysql/lib/libmysqlclient.a(my_error.o) definition of common _errbuff (size 512)
/usr/bin/libtool: internal link edit command failed

Linken Sie Qt erneut mit -single_module. Dies ist nur ein Problem, wenn Sie den MySQL-Treiber in Qt einbinden. Es wirkt sich nicht auf Plugins oder statische Builds aus.

D-Bus und macOS

Das QtDBus Modul lädt standardmäßig dynamisch die libdbus-1 Bibliothek unter macOS. Das bedeutet, dass Anwendungen, die gegen das Modul QtDBus gelinkt werden, auch auf macOS-Systemen geladen werden, die die Bibliotheken nicht haben, aber sie werden sich nicht mit einem D-Bus-Server verbinden können und sie werden keinen Server mit QDBusServer öffnen können.

Um die D-Bus-Funktionalität zu nutzen, müssen Sie die libdbus-1-Bibliothek installieren, zum Beispiel über Homebrew, Fink oder MacPorts. Sie sollten diese Bibliotheken in das Paket Ihrer Anwendung aufnehmen, wenn Sie diese auf anderen Systemen einsetzen. Beachten Sie außerdem, dass es unter macOS keinen Systembus gibt und dass der Sitzungsbus nur gestartet wird, wenn launchd so konfiguriert ist, dass er ihn verwaltet.

  • Aktionen in einem QMenu mit Beschleunigern, die mehr als einen Tastendruck (QKeySequence) haben, werden nicht korrekt angezeigt, wenn die QMenu in eine Mac native Menüleiste übersetzt wird. Die erste Taste wird angezeigt. Die Tastenkombination wird jedoch wie auf allen anderen Plattformen aktiviert.
  • QMenu Objekte, die in der nativen Menüleiste verwendet werden, sind nicht in der Lage, Qt-Ereignisse über die normalen Event-Handler zu behandeln. Installieren Sie einen Delegaten auf dem Menü selbst, um über diese Änderungen informiert zu werden. Alternativ können Sie die Signale QMenu::aboutToShow() und QMenu::aboutToHide() verwenden, um die Sichtbarkeit des Menüs zu verfolgen; diese bieten eine Lösung, die auf allen von Qt unterstützten Plattformen funktionieren sollte.
  • Standardmäßig erstellt Qt ein natives Quit-Menüelement, das auf den CMD+Q Shortcut reagiert. Das Erstellen eines QAction für die Rolle QAction::QuitRole wird diesen Menüpunkt ersetzen. Daher sollte die Ersatzaktion entweder mit dem QCoreApplication::quit Slot oder einem benutzerdefinierten Slot, der die Anwendung beendet, verbunden werden.

Native Widgets

Qt bietet Unterstützung für Sheets, die durch das Window-Flag Qt::Sheet repräsentiert werden.

Wenn man sich auf eine native macOS-Anwendung bezieht, bedeutet nativ in der Regel eine Anwendung, die direkt mit dem zugrunde liegenden Fenstersystem verbunden ist, und nicht eine, die eine Zwischenschicht verwendet. Qt-Anwendungen laufen als Bürger erster Klasse, genau wie Cocoa-Anwendungen. Wir verwenden Cocoa intern, um mit dem Betriebssystem zu kommunizieren.

Warnungen zur Sichtbarkeit von Symbolen

Im Zusammenhang mit dem Linken von C++-Bibliotheken werden Funktionen und Objekte als Symbole bezeichnet. Symbole können entweder die Sichtbarkeit default oder hidden haben.

Aus Leistungsgründen kompilieren Qt und viele andere Bibliotheken ihre Quellen standardmäßig mit der Sichtbarkeit hidden und markieren Symbole nur dann mit der Sichtbarkeit default, wenn sie in Benutzerprojekten verwendet werden sollen.

Leider kann der Apple Linker Warnungen ausgeben, wenn eine Bibliothek mit hidden Sichtbarkeit kompiliert wird und eine Benutzerprojektanwendung oder Bibliothek mit default Sichtbarkeit kompiliert wird.

Wenn Projektentwickler die Warnung ausschalten wollen, müssen sie ihren Projektcode ebenfalls mit hidden Sichtbarkeit kompilieren.

In CMake kann dies durch das Hinzufügen des folgenden Codes zu Ihrer CMakeLists.txt erfolgen:

set(CMAKE_CXX_VISIBILITY_PRESET hidden)

In qmake kann dies durch Hinzufügen des folgenden Codes zu Ihrer .pro Datei erfolgen:

CONFIG+=hide_symbols

Wenn ein Projekt Bibliotheken baut, müssen alle Symbole in der Bibliothek, die in einer anderen Bibliothek oder Anwendung verwendet werden sollen, explizit mit default sichtbar gemacht werden. Dies kann zum Beispiel dadurch geschehen, dass solche Funktionen oder Klassen mit Q_DECL_EXPORT annotiert werden.

dSYM-Bundle fehlt in xcarchive, das von einem CMake-Xcode-Projekt erstellt wurde

Aufgrund eines Fehlers in Xcode und bestimmter CMake-Beschränkungen kann es vorkommen, dass ein mit CMake erzeugtes Xcode-Projekt das dSYM -Bundle einer Anwendung nicht in ein xcarchive einbindet.

Qt bietet eine Umgehung als Opt-In, so dass das dSYM Bundle in xcarchive aufgenommen wird, aber es bringt Kompromisse mit sich. Das heißt, die folgenden CMake-Funktionen werden nicht korrekt funktionieren:

  • alle Ausdrücke des $<TARGET_FILE:app> -Generators könnten zu einem ungültigen Pfad expandieren, der nicht zur App-Binärdatei führt
  • die Variable CMAKE_RUNTIME_OUTPUT_DIRECTORY und die damit verbundene Eigenschaft RUNTIME_OUTPUT_DIRECTORY target werden ignoriert, selbst wenn sie gesetzt sind
  • andere unbekannte Probleme

Um die oben genannten Probleme zu entschärfen, können Sie:

  • die Umgehung nur dann aktivieren, wenn Sie beabsichtigen, die xcarchive zu erstellen, und nicht während der Projektentwicklung
  • sicherstellen, dass Sie nur ausführbare Dateien und Bibliotheken im Stammverzeichnis des Projekts hinzufügen und nicht in Aufrufen von add_subdirectory.

Um die Umgehung zu aktivieren, konfigurieren Sie das Projekt mit der folgenden Option:

cmake . -DQT_USE_RISKY_DSYM_ARCHIVING_WORKAROUND=ON

oder setzen Sie die Variable im Projekt vor allen Aufrufen von qt_add_executable oder qt_add_library:

set(QT_USE_RISKY_DSYM_ARCHIVING_WORKAROUND ON)

...

qt_add_executable(app)

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.