Qt pour macOS - Problèmes spécifiques
Cette page présente les principaux problèmes liés à la prise en charge de macOS dans Qt. La terminologie et les procédures spécifiques à macOS sont disponibles à l'adresse https://developer.apple.com/.
Aqua
Le style Aqua est un élément essentiel de la plateforme macOS. Comme pour Cocoa, Qt fournit des widgets dont l'apparence est conforme aux directives d'interface utilisateur de macOS. Notez que bien que les widgets Qt utilisent AppKit en arrière-plan pour leur apparence et leur comportement, cela ne signifie pas que chaque widget Qt soit représenté sous la forme d'un contrôle natif encapsulé.
La page « Galerie des Qt Widgets » contient des exemples d'images d'applications utilisant le thème de la plateforme macOS.
Attributs Qt pour macOS
Vous trouverez ci-dessous une liste d'attributs utiles permettant de personnaliser les applications sous macOS :
- Qt::AA_PluginApplication
- Qt::AA_DontUseNativeMenuBar
- Qt::AA_MacDontSwapCtrlAndMeta
- Qt::WA_MacOpaqueSizeGrip
- Qt::WA_MacShowFocusRect
- Qt::WA_MacNormalSize
- Qt::WA_MacSmallSize
- Qt::WA_MacMiniSize
- Qt::WA_MacAlwaysShowToolWindow
- Qt::Sheet
- Qt::Drawer
- Qt::MacWindowToolBarButtonHint,
- QMainWindow::unifiedTitleAndToolBarOnMac
macOS utilise toujours un double tampon pour l'écran ; par conséquent, l'attribut ` Qt::WA_PaintOnScreen ` n'a aucun effet. De même, il est impossible de dessiner en dehors d'un événement de dessin ; l'attribut `Qt::WA_PaintOutsidePaintEvent` n'a donc aucun effet non plus.
Clics droits de la souris
La classe ` QContextMenuEvent ` prend en charge les clics avec le bouton droit de la souris pour les applications macOS. Cela correspond à un événement de menu contextuel, par exemple un menu affichant une sélection contextuelle. Il s'agit de l'utilisation la plus courante des clics avec le bouton droit de la souris, qui correspond à un clic avec la touche Ctrl enfoncée dans le cadre de la prise en charge des souris à un seul bouton sous macOS.
Internationalisation
Les applications sous macOS déclarent les langues qu’elles prennent en charge dans le cadre de l’ Info.plist de l’application. Le système fait ensuite correspondre les langues prises en charge par l’application avec les préférences linguistiques de l’utilisateur afin de déterminer la locale dans laquelle l’application sera lancée. Cela détermine à son tour l’ordre des langues reflété par la fonction ` QLocale::uiLanguages()`, ainsi que la manière dont les frameworks système tels qu’AppKit récupèrent leurs ressources localisées, comme les titres de menu et les chaînes de caractères.
Comme les applications Qt ne sont pas traduites par défaut, le fichier ` Info.plist ` généré par défaut pour les projets ` CMake ` et ` qmake ` définit CFBundleAllowMixedLocalizations sur YES, afin de permettre aux frameworks système de sélectionner la localisation qui correspond le mieux aux préférences linguistiques de l’utilisateur, même si cette localisation n’est pas disponible pour l’application elle-même. Une fois que vous avez ajouté des traductions à votre application via qt_add_translations, la CFBundleAllowMixedLocalizations clé sera automatiquement supprimée et remplacée par CFBundleLocalizations, répertoriant toutes les langues que vous prenez en charge. Pour qmake, cette opération doit être effectuée manuellement.
Barre de menus
Qt détecte les barres de menus et les transforme en barres de menus natives Mac. L'intégration de cette fonctionnalité dans les applications Qt existantes est généralement automatique. Toutefois, si vous avez des besoins particuliers, l'implémentation Qt sélectionne actuellement une barre de menus en commençant par la fenêtre active (par exemple, QGuiApplication::focusWindow()) et en appliquant les tests suivants :
- Si la fenêtre dispose d’un QMenuBar, celui-ci est utilisé.
- Si la fenêtre est modale, c’est sa barre de menus qui est utilisée. Si aucune barre de menus n’est spécifiée, c’est une barre de menus par défaut qui est utilisée (comme indiqué ci-dessous).
- Si la fenêtre n’a pas de fenêtre parente, la barre de menus par défaut est utilisée (comme indiqué ci-dessous).
Ces vérifications sont effectuées tout au long de la chaîne des fenêtres parentes jusqu’à ce que l’une des règles ci-dessus soit satisfaite. Si toutes les autres solutions échouent, une barre de menus par défaut sera créée. La barre de menus par défaut sous Qt est une barre de menus vide. Cependant, vous pouvez créer une barre de menus par défaut différente en créant une ` QMenuBar` sans parent. La première créée sera désignée comme barre de menus par défaut et sera utilisée chaque fois qu’une barre de menus par défaut est nécessaire.
L’utilisation de barres de menus natives impose certaines limitations aux classes Qt. Vous trouverez plus d’informations à ce sujet dans la section ci-dessous répertoriant ces limitations.
Qt prend en charge la barre de menus globale via ` QMenuBar`. Les utilisateurs de macOS s’attendent à disposer d’une barre de menus en haut de l’écran, et Qt respecte cette convention.
De plus, les utilisateurs s'attendent à ce que certaines conventions soient respectées ; par exemple, le menu de l'application doit contenir les éléments « À propos », « Préférences », « Quitter », etc. Qt prend en charge ces conventions, bien qu'il ne fournisse pas de moyen d'interagir directement avec le menu de l'application.
Chaque QAction dispose d’une propriété menuRole qui contrôle l’emplacement spécifique des éléments du menu de l’application ; cependant, par défaut, la menuRole est TextHeuristicRole, ce qui signifie que les éléments du menu seront détectés automatiquement en fonction de leur text.
D'autres éléments de menu standard, tels que « Couper », « Copier », « Coller » et « Tout sélectionner », s'appliquent à la fois à votre application et à certaines boîtes de dialogue natives, telles que QFileDialog. Il est important que vous créiez ces éléments de menu avec les raccourcis standard afin que les fonctionnalités d'édition correspondantes soient activées dans les boîtes de dialogue. Pour l’instant, il n’existe pas d’identificateurs « MenuRole » pour ces éléments, mais ils seront détectés automatiquement, tout comme les éléments du menu de l’application, lorsque l’ QAction e utilise l’ TextHeuristicRole par défaut.
Touches spéciales
Afin d’assurer le comportement attendu des applications Qt sous macOS, les valeurs des énumérations Qt::Key_Meta, Qt::MetaModifier et Qt::META correspondent aux touches Contrôle du clavier Apple standard, tandis que les valeurs des énumérations Qt::Key_Control, Qt::ControlModifier et Qt::CTRL correspondent aux touches Commande.
Dock
L'interaction avec le Dock est possible. L'icône peut être définie en appelant la méthode QWindow::setIcon() depuis la fenêtre principale de votre application. L'appel à setIcon() peut être effectué aussi souvent que nécessaire, ce qui permet de mettre facilement à jour l'icône.
Accessibilité
De nombreux utilisateurs interagissent avec macOS à l'aide de dispositifs d'assistance. Avec Qt, l'objectif est de rendre ce processus automatique dans votre application afin qu'elle soit conforme aux pratiques reconnues sur sa plateforme. Qt utilise le framework d'accessibilité d'Apple pour faciliter l'accès aux utilisateurs en situation de handicap.
Prise en charge des bibliothèques et du déploiement
Qt prend en charge les structures de macOS telles que les Frameworks et les bundles. Il est important de bien connaître ces structures, car elles ont une incidence directe sur le déploiement des applications.
Qt fournit un outil de déploiement, macdeployqt, afin de simplifier le processus de déploiement. L'article « Qt pour macOS - Déploiement » traite du processus de déploiement plus en détail.
Les bibliothèques Qt en tant que Frameworks
Par défaut, Qt est compilé sous forme d'un ensemble de frameworks. Les frameworks constituent le mode de distribution des bibliothèques privilégié par macOS. Le site du Guide de programmation des frameworks d'Apple fournit de nombreuses informations supplémentaires sur les frameworks.
Il est important de garder à l’esprit que les frameworks sont toujours liés aux versions de production des bibliothèques. Si vous souhaitez utiliser la version de débogage d’un framework Qt, utilisez les variables d’environnement ` DYLD_IMAGE_SUFFIX ` pour vous assurer que la version de débogage est bien chargée :
export DYLD_IMAGE_SUFFIX=_debugVous pouvez également permuter temporairement vos versions de débogage et de production, comme indiqué dans la note technique « Debugging Magic » d’Apple.
Si vous ne souhaitez pas utiliser de frameworks, configurez simplement Qt avec -no-framework.
./configure -no-frameworkBibliothèques sous forme de bundles
Si vous souhaitez utiliser des bibliothèques dynamiques dans le bundle de l'application macOS (le répertoire de l'application), créez un sous-répertoire nommé « Frameworks » dans le répertoire du bundle de l'application et placez-y vos bibliothèques dynamiques. L'application trouvera une bibliothèque dynamique si son nom d'installation est @executable_path/../Frameworks/libname.dylib.
Si vous utilisez des fichiers « qmake » et des Makefiles, utilisez le paramètre « QMAKE_LFLAGS_SONAME » :
QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../Frameworks/Vous pouvez également modifier le nom d’installation à l’aide de l’option « install_name_tool(1) » sur la ligne de commande.
La variable d’environnement ` DYLD_LIBRARY_PATH ` prévaudra sur ces paramètres, ainsi que sur tout autre chemin par défaut, tel que la recherche de bibliothèques dynamiques dans `/usr/lib ` et d’autres emplacements par défaut similaires.
Combinaison de bibliothèques
Si vous souhaitez compiler une nouvelle bibliothèque dynamique combinant les bibliothèques dynamiques Qt, vous devez utiliser l’option ld -r. Les informations de relocalisation sont alors stockées dans le fichier de sortie, ce qui permet d’utiliser ce fichier pour une nouvelle exécution de ` ld `. Pour ce faire, définissez l’option -r dans le fichier .pro et configurez les paramètres LFLAGS.
Ordre d’initialisation
dyld(1) appelle les initialiseurs statiques globaux dans l’ordre où ils sont liés à l’application. Si une bibliothèque est liée à Qt et fait référence aux variables globales de Qt (à partir d’initialiseurs globaux de votre propre bibliothèque), liez l’application à Qt avant de la lier à la bibliothèque. Sinon, le résultat sera indéfini car les initialiseurs globaux de Qt n’auront pas encore été appelés.
Options de compilation
Les options suivantes sont utiles lorsque vous souhaitez définir du code spécifique à macOS :
Q_OS_DARWINest défini lorsque Qt détecte que vous utilisez un système basé sur Darwin, tel que macOS ou iOS.Q_OS_MACOSest défini lorsque vous utilisez un système macOS.
Remarque : ` Q_WS_MAC ` n'est plus défini dans Qt 5 et les versions ultérieures.
Si vous souhaitez définir du code pour des versions spécifiques de macOS, utilisez les macros de disponibilité définies dans /usr/include/AvailabilityMacros.h.
La documentation relative à QSysInfo et QOperatingSystemVersion contient des informations sur la vérification de la version lors de l'exécution.
Accès à l'API native de macOS
Accès au chemin d'accès du bundle
Les applications macOS sont structurées sous la forme d’un répertoire (se terminant par .app). Ce répertoire contient des sous-répertoires et des fichiers. Il peut être utile de placer des éléments, tels que des plug-ins et de la documentation en ligne, à l’intérieur de ce bundle. Le code suivant renvoie le chemin d’accès au bundle de l’application :
#ifdef Q_OS_MAC
QString bundlePath = QString::fromNSString(NSBundle.mainBundle.bundlePath);
qDebug() << "Bundle path =" << bundlePath;
#endifPour plus d'informations sur l'utilisation de l'API NSBundle, rendez-vous sur le site Web des développeurs d'Apple.
QCoreApplication::applicationDirPathLa fonction () permet de déterminer le chemin d’accès au fichier binaire au sein du bundle.
Utilisation des panneaux Cocoa natifs
Le répartiteur d’événements de Qt est plus flexible que celui proposé par Cocoa et permet à l’utilisateur de le déclencher (et d’exécuter QEventLoop::exec) sans avoir à se soucier de la présence ou non de boîtes de dialogue modales à l’écran (ce qui constitue une différence par rapport à Cocoa). Par conséquent, nous devons mettre en place une gestion supplémentaire dans Qt pour gérer cela correctement, ce qui rend malheureusement difficile l’intégration de panneaux natifs. La meilleure façon de procéder pour l'instant consiste à suivre le modèle ci-dessous, dans lequel nous transmettons l'appel à la fonction via du code natif plutôt que de l'appeler directement. Nous sommes ainsi assurés que Qt a correctement mis à jour toutes les récursions en attente de la boucle d'événements avant l'affichage du panneau natif :
#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();
}Limites
MySQL et macOS
Il semble y avoir un problème lorsque les variables d'environnement -prebind et -multi_module sont toutes deux définies lors de la liaison de bibliothèques C statiques à des bibliothèques dynamiques. Si vous obtenez le message d'erreur suivant lors de la liaison de 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 failedreliez Qt à l'aide de l'option -single_module. Ce problème ne se pose que lors de l'intégration du pilote MySQL dans Qt. Il n'affecte pas les plugins ni les compilations statiques.
D-Bus et macOS
Par défaut, le module ` QtDBus ` charge dynamiquement la bibliothèque `libdbus-1` sous macOS. Cela signifie que les applications liées au module ` QtDBus ` se chargeront même sur les systèmes macOS ne disposant pas de ces bibliothèques, mais elles ne pourront se connecter à aucun serveur D-Bus et ne parviendront pas à ouvrir un serveur à l'aide de ` QDBusServer`.
Pour utiliser les fonctionnalités de D-Bus, vous devez installer la bibliothèque libdbus-1, par exemple via Homebrew, Fink ou MacPorts. Vous pouvez inclure ces bibliothèques dans le bundle de votre application si vous la déployez sur d’autres systèmes. Notez également qu’il n’existe pas de bus système sous macOS et que le bus de session ne sera lancé qu’une fois que launchd aura été configuré pour le gérer.
Actions du menu
- Les actions d’une « QMenu » (raccourcis clavier comportant plusieurs touches) (QKeySequence) ne s’afficheront pas correctement lorsque l’ QMenu sera converti en barre de menus native Mac. Seule la première touche sera affichée. Cependant, le raccourci sera toujours activé comme sur toutes les autres plateformes.
- QMenu Les objets utilisés dans la barre de menus native ne sont pas capables de gérer les événements Qt via les gestionnaires d’événements habituels. Installez un délégué sur le menu lui-même pour être averti de ces changements. Vous pouvez également envisager d’utiliser les signaux ` QMenu::aboutToShow()` et ` QMenu::aboutToHide()` pour suivre la visibilité du menu ; ceux-ci offrent une solution qui devrait fonctionner sur toutes les plateformes prises en charge par Qt.
- Par défaut, Qt crée un élément de menu natif « Quitter » qui réagit au raccourci
CMD+Q. La création d’un QAction pour le rôle QAction::QuitRole remplacera cet élément de menu. Par conséquent, l’action de remplacement doit être connectée soit au slot QCoreApplication::quit, soit à un slot personnalisé qui arrête l’application.
Widgets natifs
Qt prend en charge les feuilles (sheets), représentées par l'indicateur de fenêtre Qt::Sheet.
En général, lorsqu'on parle d'une application native sous macOS, le terme « native » désigne une application qui s'interface directement avec le système de fenêtrage sous-jacent, plutôt qu'une application utilisant une couche intermédiaire. Les applications Qt s'exécutent au même titre que les applications Cocoa. Nous utilisons Cocoa en interne pour communiquer avec le système d'exploitation.
Avertissements relatifs à la visibilité des symboles
Dans le cadre de la liaison de bibliothèques C++, les fonctions et les objets sont appelés « symboles ». Les symboles peuvent avoir une visibilité « default » ou « hidden ».
Pour des raisons de performances, Qt et de nombreuses autres bibliothèques compilent leurs sources en utilisant par défaut la visibilité « hidden » et ne marquent les symboles avec la visibilité « default » que lorsqu’ils sont destinés à être utilisés dans les projets des utilisateurs.
Malheureusement, l’éditeur de liens Apple peut générer des avertissements lorsqu’une bibliothèque est compilée avec la visibilité « hidden » et qu’une application ou une bibliothèque d’un projet utilisateur est compilée avec la visibilité « default ».
Si les développeurs du projet souhaitent désactiver cet avertissement, ils doivent également compiler le code de leur projet avec une visibilité « hidden ».
Dans CMake, cela peut être réalisé en ajoutant le code suivant à votre fichier ` CMakeLists.txt` :
set(CMAKE_CXX_VISIBILITY_PRESET hidden)Dans qmake, cela peut être fait en ajoutant le code suivant à votre fichier ` .pro ` :
CONFIG+=hide_symbolsSi un projet compile des bibliothèques, tous les symboles de la bibliothèque destinés à être utilisés dans une autre bibliothèque ou application devront être explicitement marqués avec la visibilité « default ». Par exemple, cela peut être fait en annotant ces fonctions ou classes avec ` Q_DECL_EXPORT`.
Absence du bundle dSYM dans l'archive xcarchive créée par un projet CMake Xcode
En raison d’un bug dans Xcode et de certaines limitations de CMake, un projet Xcode généré par CMake ne parviendra pas à inclure le bundle « dSYM » d’une application dans un « xcarchive » lors de la tâche d’archivage d’Xcode.
Qt propose une solution de contournement optionnelle permettant d’inclure le bundle « dSYM » dans l’ xcarchive, mais celle-ci comporte des inconvénients. En effet, les fonctionnalités CMake suivantes ne fonctionneront pas correctement :
- toute expression de générateur de `
$<TARGET_FILE:app>` risque de se développer en un chemin invalide ne menant pas au binaire de l’application - la variable
CMAKE_RUNTIME_OUTPUT_DIRECTORYet la propriété de cibleRUNTIME_OUTPUT_DIRECTORYqui lui est associée seront ignorées même si elles sont définies - d'autres problèmes inconnus
Pour pallier les problèmes ci-dessus, vous pouvez :
- n'activer la solution de contournement que lorsque vous avez l'intention de créer l'
xcarchive, et non pendant le développement du projet - veiller à n'ajouter des exécutables et des bibliothèques que dans le répertoire racine du projet, et non dans les appels d'
add_subdirectory.
Pour activer la solution de contournement, configurez le projet à l'aide de l'option suivante :
cmake . -DQT_USE_RISKY_DSYM_ARCHIVING_WORKAROUND=ONou définissez la variable dans le projet avant tout appel à ` qt_add_executable ` ou ` qt_add_library ` :
set(QT_USE_RISKY_DSYM_ARCHIVING_WORKAROUND ON)
...
qt_add_executable(app)© 2026 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.