Qt para macOS - Problemas específicos
En esta página se describen los principales problemas relacionados con la compatibilidad de Qt con macOS. La terminología y los procesos específicos de macOS se encuentran en https://developer.apple.com/.
Aqua
El estilo Aqua es una parte esencial de la plataforma macOS. Al igual que con Cocoa, Qt proporciona widgets que se parecen a los descritos en las Directrices de Interfaz Humana de macOS. Tenga en cuenta que aunque los widgets de Qt utilizan AppKit bajo el capó para el aspecto y la sensación, no representa cada Qt Widget individual como un control nativo envuelto.
La página Qt Widget Gallery contiene imágenes de ejemplo de aplicaciones que utilizan el tema de la plataforma macOS.
Atributos de Qt para macOS
A continuación se enumera un conjunto de atributos útiles que pueden utilizarse para ajustar las aplicaciones en 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 siempre hace doble buffer en la pantalla, por lo tanto, el atributo Qt::WA_PaintOnScreen no tiene efecto. También es imposible pintar fuera de un evento paint por lo que Qt::WA_PaintOutsidePaintEvent tampoco tiene efecto.
Clics con el botón derecho del ratón
La clase QContextMenuEvent proporciona soporte para el botón derecho del ratón para aplicaciones macOS. Esto se asignará a un evento de menú contextual, por ejemplo, un menú que mostrará una selección emergente. Este es el uso más común de los clics con el botón derecho del ratón, y se asigna a un control-clic con el soporte de ratón de un botón de macOS.
Internacionalización
Las aplicaciones en macOS declaran sus idiomas compatibles como parte de Info.plist de la aplicación. A continuación, el sistema cotejará los idiomas admitidos de la aplicación con las preferencias de idioma del usuario para determinar la configuración regional en la que se inicia la aplicación. Esto a su vez determina los idiomas ordenados reflejados a través de QLocale::uiLanguages(), y cómo los marcos del sistema como AppKit recogen sus recursos localizados, como títulos de menú y cadenas.
Como las aplicaciones Qt no se traducen de forma automática, el Info.plist generado por defecto para los proyectos CMake y qmake establece CFBundleAllowMixedLocalizations a YES, para permitir que los frameworks del sistema elijan la localización que mejor se adapte a las preferencias de idioma del usuario, incluso si esa localización no está disponible para la propia aplicación. Una vez que añada traducciones a su aplicación mediante qt_add_translations, la clave CFBundleAllowMixedLocalizations se eliminará automáticamente y se sustituirá por CFBundleLocalizationsque enumera todos los idiomas que admite. Para qmake este proceso debe hacerse manualmente.
Barra de menús
Qt detecta las barras de menú y las convierte en barras de menú nativas de Mac. Normalmente, la adaptación a las aplicaciones Qt existentes es automática. Sin embargo, si tiene necesidades especiales, la implementación de Qt actualmente selecciona una barra de menú comenzando en la ventana activa (por ejemplo, QGuiApplication::focusWindow()) y aplicando las siguientes pruebas:
- Si la ventana tiene un QMenuBar, entonces se utiliza.
- Si la ventana es modal, se utiliza su barra de menús. Si no se especifica ninguna barra de menú, se utiliza una barra de menú por defecto (como se documenta más adelante).
- Si la ventana no tiene padre, entonces se utiliza la barra de menú por defecto (como se documenta más adelante).
Estas pruebas se siguen a lo largo de toda la cadena de ventanas padre hasta que se cumple una de las reglas anteriores. Si todo lo demás falla, se creará una barra de menú por defecto. La barra de menú por defecto en Qt es una barra de menú vacía. Sin embargo, puede crear una barra de menú por defecto diferente creando una sin padre QMenuBar. La primera que se cree se designará como barra de menú por defecto y se utilizará siempre que se necesite una barra de menú por defecto.
El uso de barras de menú nativas introduce ciertas limitaciones en las clases Qt. La sección con la lista de limitaciones más abajo tiene más información.
Qt proporciona soporte para la Barra de Menú Global con QMenuBar. Los usuarios de macOS esperan tener una barra de menú en la parte superior de la pantalla y Qt lo cumple.
Además, los usuarios esperan que se respeten ciertas convenciones, por ejemplo que el menú de la aplicación contenga Acerca de, Preferencias, Salir, etcétera. Qt maneja estas convenciones, aunque no proporciona un medio para interactuar directamente con el menú de la aplicación.
Cada QAction tiene una propiedad menuRole que controla la colocación especial de los elementos del menú de la aplicación; sin embargo, por defecto menuRole es TextHeuristicRole, lo que significa que los elementos del menú serán autodetectados por su text.
Otros elementos de menú estándar como Cortar, Copiar, Pegar y Seleccionar todo son aplicables tanto en su aplicación como en algunos diálogos nativos como QFileDialog. Es importante que crees estos elementos de menú con los atajos estándar para que las funciones de edición correspondientes se activen en los diálogos. En este momento no hay identificadores MenuRole para ellos, pero serán autodetectados al igual que los elementos de menú de la aplicación cuando el QAction tenga el valor por defecto TextHeuristicRole.
Teclas especiales
Para proporcionar el comportamiento esperado para aplicaciones Qt en macOS, los valores Qt::Key_Meta, Qt::MetaModifier, y Qt::META enum corresponden a las teclas Control del teclado Apple estándar, y los valores Qt::Key_Control, Qt::ControlModifier, y Qt::CTRL enum corresponden a las teclas Comando.
Muelle
Es posible interactuar con el Dock. El icono se puede establecer llamando a QWindow::setIcon() desde la ventana principal de tu aplicación. La llamada a setIcon() puede realizarse tantas veces como sea necesario, proporcionando un icono que puede actualizarse fácilmente.
Accesibilidad
Muchos usuarios interactúan con macOS mediante dispositivos de asistencia. Con Qt el objetivo es hacer que esto sea automático en su aplicación para que se ajuste a las prácticas aceptadas en su plataforma. Qt utiliza el marco de accesibilidad de Apple para facilitar el acceso a usuarios con discapacidad.
Biblioteca y soporte de despliegue
Qt proporciona soporte para estructuras de macOS como Frameworks y bundles. Es importante conocer estas estructuras ya que afectan directamente al despliegue de las aplicaciones.
Qt proporciona una herramienta de despliegue, macdeployqt, para simplificar el proceso de despliegue. El artículo Qt para macOS - Despliegue cubre el proceso de despliegue con más detalle.
Bibliotecas Qt como Frameworks
Por defecto, Qt se construye como un conjunto de frameworks. Los frameworks son la forma preferida de macOS para distribuir bibliotecas. El sitio de la Guía de Programación de Frameworks de Apple tiene mucha más información sobre Frameworks.
Es importante recordar que los frameworks siempre se enlazan con las versiones de lanzamiento de las bibliotecas. Si se desea la versión de depuración de un framework Qt, utilice las variables de entorno DYLD_IMAGE_SUFFIX para asegurarse de que se carga la versión de depuración:
export DYLD_IMAGE_SUFFIX=_debug
Alternativamente, puedes intercambiar temporalmente las versiones de depuración y de lanzamiento, lo cual está documentado en la nota técnica de Apple "Debugging Magic".
Si no quieres usar frameworks, simplemente configura Qt con -no-framework.
./configure -no-framework
Bibliotecas basadas en paquetes
Si desea utilizar algunas bibliotecas dinámicas en el bundle de la aplicación macOS (el directorio de la aplicación), cree un subdirectorio llamado Frameworks en el directorio del bundle de la aplicación y coloque allí sus bibliotecas dinámicas. La aplicación encontrará una biblioteca dinámica si tiene el nombre de instalación @ruta_ejecutable/../Frameworks/nombre_de_la_aplicación.dylib.
Si utiliza qmake y Makefiles, utilice la configuración QMAKE_LFLAGS_SONAME:
QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../Frameworks/
Alternativamente, puede modificar el nombre de instalación utilizando install_name_tool(1) en la línea de comandos.
La variable de entorno DYLD_LIBRARY_PATH anulará estos ajustes, y cualquier otra ruta por defecto, como una búsqueda de bibliotecas dinámicas dentro de /usr/lib y ubicaciones similares por defecto.
Combinación de bibliotecas
Si desea construir una nueva biblioteca dinámica combinando las bibliotecas dinámicas Qt, necesita introducir la bandera ld -r. Entonces la información de reubicación se almacena en el fichero de salida, de forma que este fichero pueda ser objeto de otra ejecución de ld. Esto se hace estableciendo la bandera -r en el archivo .pro, y la configuración LFLAGS.
Orden de inicialización
dyld(1) llama a los inicializadores estáticos globales en el orden en que están enlazados en la aplicación. Si una librería enlaza contra Qt y hace referencia a los globales en Qt (desde inicializadores globales en tu propia librería), enlaza la aplicación contra Qt antes de enlazarla contra la librería. De lo contrario, el resultado será indefinido porque los inicializadores globales de Qt aún no han sido llamados.
Banderas de tiempo de compilación
Los siguientes indicadores son útiles cuando se desea definir código específico para macOS:
Q_OS_DARWINse define cuando Qt detecta que estás en un sistema basado en Darwin como macOS o iOS.Q_OS_MACOSse define cuando estás en un sistema macOS.
Nota: Q_WS_MAC ya no está definido en Qt 5 y posteriores.
Si quieres definir código para versiones específicas de macOS, utiliza las macros de disponibilidad definidas en /usr/include/AvailabilityMacros.h.
La documentación de QSysInfo y QOperatingSystemVerison tiene información sobre la comprobación de versiones en tiempo de ejecución.
Acceso a la API nativa de macOS
Acceso a la ruta del paquete
Las aplicaciones de macOS están estructuradas como un directorio (que termina en .app). Este directorio contiene subdirectorios y archivos. Puede ser útil colocar elementos, como plugins y documentación online, dentro de este bundle. El siguiente código devuelve la ruta del paquete de aplicaciones:
#ifdef Q_OS_MAC QString bundlePath = QString::fromNSString(NSBundle.mainBundle.bundlePath); qDebug() << "Bundle path =" << bundlePath; #endif
Para obtener más información sobre el uso de la API NSBundle, visite el sitio web para desarrolladores de Apple.
QCoreApplication::applicationDirPath() puede utilizarse para determinar la ruta del binario dentro del bundle.
Uso de paneles Cocoa nativos
El despachador de eventos de Qt es más flexible que lo que Cocoa ofrece, y permite al usuario girar el despachador de eventos (y ejecutar QEventLoop::exec) sin tener que pensar en si se están mostrando o no diálogos modales en pantalla (lo cual es una diferencia comparado con Cocoa). Por lo tanto, necesitamos hacer una gestión extra en Qt para manejar esto correctamente, lo que desafortunadamente hace que mezclar paneles nativos sea difícil. La mejor manera por el momento de hacer esto, es seguir el patrón de abajo, donde posteamos la llamada a la función con código nativo en lugar de llamarla directamente. Entonces sabemos que Qt ha actualizado limpiamente cualquier recurrencia pendiente del bucle de eventos antes de que se muestre el panel nativo:
#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(); }
Limitaciones
MySQL y macOS
Parece haber un problema cuando se definen tanto -prebind como -multi_module al enlazar bibliotecas C estáticas con bibliotecas dinámicas. Si aparece el siguiente mensaje de error al enlazar 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
vuelva a enlazar Qt usando -single_module. Esto sólo es un problema cuando se construye el controlador MySQL en Qt. No afecta a plugins o construcciones estáticas.
D-Bus y macOS
El módulo QtDBus carga dinámicamente por defecto la librería libdbus-1 en macOS. Esto significa que las aplicaciones que enlazan con el módulo QtDBus se cargarán incluso en sistemas macOS que no tengan las bibliotecas, pero no podrán conectarse a ningún servidor D-Bus y no podrán abrir un servidor que utilice QDBusServer.
Para usar la funcionalidad D-Bus, necesitas instalar la librería libdbus-1, por ejemplo a través de Homebrew, Fink o MacPorts. Puede que quieras incluir esas librerías en el bundle de tu aplicación si vas a desplegarla en otros sistemas. Además, ten en cuenta que no hay bus de sistema en macOS y que el bus de sesión sólo se iniciará después de que launchd esté configurado para gestionarlo.
Menú Acciones
- Las acciones en un QMenu con aceleradores que tienen más de una pulsación de tecla (QKeySequence) no se mostrarán correctamente, cuando el QMenu se traduce en una barra de menú nativa de Mac. Se mostrará la primera tecla. Sin embargo, el acceso directo se seguirá activando como en el resto de plataformas.
- QMenu Los objetos usados en la barra de menú nativa no son capaces de manejar eventos Qt a través de los manejadores de eventos normales. Instale un delegado en el propio menú para ser notificado de estos cambios. Como alternativa, considere el uso de las señales QMenu::aboutToShow() y QMenu::aboutToHide() para realizar un seguimiento de la visibilidad del menú; éstas proporcionan una solución que debería funcionar en todas las plataformas soportadas por Qt.
- Por defecto, Qt crea un elemento de menú nativo Quit que reaccionará al acceso directo
CMD+Q. Crear un QAction para el rol QAction::QuitRole reemplazará ese elemento de menú. Por lo tanto, la acción de reemplazo debe estar conectada a la ranura QCoreApplication::quit, o a una ranura personalizada que detenga la aplicación.
Widgets nativos
Qt tiene soporte para hojas, representadas por la bandera de ventana, Qt::Sheet.
Normalmente, cuando nos referimos a una aplicación nativa de macOS, nativo significa una aplicación que interactúa directamente con el sistema de ventanas subyacente, en lugar de una que utiliza alguna capa intermediaria. Las aplicaciones Qt se ejecutan como ciudadanos de primera clase, al igual que las aplicaciones Cocoa. Utilizamos Cocoa internamente para comunicarnos con el sistema operativo.
Advertencias de visibilidad de símbolos
En el contexto de la vinculación de bibliotecas C++, las funciones y los objetos se denominan símbolos. Los símbolos pueden tener visibilidad en default o hidden.
Por razones de rendimiento, Qt y muchas otras bibliotecas compilan sus fuentes utilizando la visibilidad hidden por defecto, y sólo marcan los símbolos con la visibilidad default cuando están destinados a ser utilizados en proyectos de usuario.
Desafortunadamente, el enlazador de Apple puede emitir advertencias cuando una librería se compila con visibilidad hidden y una aplicación o librería de un proyecto de usuario se compila con visibilidad default.
Si los desarrolladores de proyectos quieren silenciar la advertencia, tienen que compilar el código de su proyecto también con visibilidad hidden.
En CMake se puede hacer añadiendo el siguiente código a su CMakeLists.txt:
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
En qmake que se puede hacer mediante la adición del siguiente código a su .pro archivo:
CONFIG+=hide_symbols
En caso de que un proyecto construya librerías, cualquier símbolo en la librería que vaya a ser usado en otra librería o aplicación tendrá que ser marcado explícitamente con la visibilidad default. Por ejemplo, esto puede hacerse anotando dichas funciones o clases con Q_DECL_EXPORT.
dSYM paquete que falta en xcarchive creado por un proyecto CMake Xcode
Debido a un error en Xcode y a ciertas limitaciones de CMake, un proyecto Xcode generado por CMake no incluirá el paquete dSYM de una aplicación en xcarchive, durante la tarea de archivado de Xcode.
Qt ofrece una solución opcional para que el paquete dSYM se incluya en xcarchive, pero tiene sus inconvenientes. Es decir, las siguientes características de CMake no funcionarán correctamente:
- cualquier expresión del generador
$<TARGET_FILE:app>podría expandirse a una ruta no válida que no lleve al binario de la aplicación - la variable
CMAKE_RUNTIME_OUTPUT_DIRECTORYy su propiedad de destino asociadaRUNTIME_OUTPUT_DIRECTORYse ignorarán incluso si se establecen - otros problemas desconocidos
Para mitigar los problemas anteriores, puede:
- activar la solución sólo cuando vaya a crear
xcarchivey no durante el desarrollo del proyecto - asegúrate de que sólo añades ejecutables y bibliotecas en el directorio raíz del proyecto, y no en las llamadas a
add_subdirectory.
Para activar la solución, configure el proyecto con la siguiente opción:
cmake . -DQT_USE_RISKY_DSYM_ARCHIVING_WORKAROUND=ON
o establezca la variable en el proyecto antes de cualquier llamada a qt_add_executable o 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.