Spec-Zone.ru › Qt 5.14

Qt для macOS — Особенности

На этой странице описаны основные проблемы, связанные с поддержкой macOS в Qt. Термины и специфические процессы macOS можно найти на сайте https://developer.apple.com/.

Aqua

Стиль Aqua является неотъемлемой частью платформы macOS. Как и Cocoa, Qt предоставляет виджеты, которые выглядят так же, как описано в Руководстве по разработке пользовательского интерфейса macOS. Обратите внимание, что, хотя виджеты Qt используют AppKit для внешнего вида, каждый отдельный виджет Qt не представлен как обернутый родной элемент управления.

На странице Галерея виджетов Qt содержатся примеры изображений приложений, использующих тему платформы macOS.

Атрибуты Qt для macOS

Ниже представлен список полезных атрибутов, которые можно использовать для настройки приложений на macOS:

  • Qt::AA_MacPluginApplication
  • Qt::AA_DontUseNativeMenuBar
  • Qt::AA_MacDontSwapCtrlAndMeta
  • Qt::WA_MacNoClickThrough
  • Qt::WA_MacOpaqueSizeGrip
  • Qt::WA_MacShowFocusRect
  • Qt::WA_MacNormalSize
  • Qt::WA_MacSmallSize
  • Qt::WA_MacMiniSize
  • Qt::WA_MacVariableSize
  • Qt::WA_MacBrushedMetal
  • Qt::WA_MacAlwaysShowToolWindow
  • Qt::WA_MacFrameworkScaled
  • Qt::WA_MacNoShadow
  • Qt::Sheet
  • Qt::Drawer
  • Qt::MacWindowToolBarButtonHint,
  • QMainWindow::unifiedTitleAndToolBarOnMac

macOS всегда использует двойную буферизацию экрана, поэтому атрибут Qt::WA_PaintOnScreen не оказывает никакого влияния. Также невозможно рисовать вне события рисования, поэтому атрибут Qt::WA_PaintOutsidePaintEvent также не оказывает никакого влияния.

Нажатия правой кнопкой мыши

Класс QContextMenuEvent обеспечивает поддержку нажатия правой кнопкой мыши для приложений macOS. Это будет соответствовать событию контекстного меню, например, меню, которое отобразит всплывающее меню выбора. Это наиболее распространённое использование нажатия правой кнопкой мыши и соответствует нажатию клавиши Control на мыши с одной кнопкой в macOS.

Панель меню

Qt обнаруживает панели меню и преобразует их в родные панели меню macOS. Встраивание в существующие приложения Qt обычно происходит автоматически. Однако, если у вас есть особые потребности, текущая реализация Qt выбирает панель меню, начиная с активного окна (например, QGuiApplication::focusWindow() и применяя следующие тесты:

  1. Если у окна есть QMenuBar, то он используется.
  2. Если окно модальное, то используется его панель меню. Если панель меню не указана, используется стандартная панель меню (как описано ниже).
  3. Если у окна нет родителя, используется стандартная панель меню (как описано ниже).

Эти тесты выполняются по всей цепочке родительских окон до тех пор, пока не будет удовлетворено одно из вышеперечисленных правил. Если ничего не подходит, будет создана стандартная панель меню. Стандартная панель меню в Qt — пустая панель меню. Однако вы можете создать другую стандартную панель меню, создав родительский QMenuBar. Первый созданный элемент будет обозначен как стандартная панель меню и будет использоваться всякий раз, когда нужна стандартная панель меню.

Использование родных панелей меню вводит определённые ограничения на классы Qt. Подробную информацию о списка ограничений см. в разделе ограничения.

Qt поддерживает глобальную панель меню с помощью QMenuBar. Пользователи macOS ожидают наличие панели меню в верхней части экрана, и Qt поддерживает это ожидание.

Кроме того, пользователи ожидают соблюдения определённых конвенций, например, меню приложения должно содержать пункты О программе, Настройки, Выход и так далее. Qt соблюдает эти конвенции, но не предоставляет способов прямого взаимодействия с меню приложения.

Каждый QAction имеет свойство menuRole, которое управляет специальным расположением элементов меню приложения; однако по умолчанию menuRole является TextHeuristicRole, что означает, что элементы меню будут автоматически определяться по их text.

Другие стандартные пункты меню, такие как Вырезать, Копировать, Вставить и Выделить все, применимы как в вашем приложении, так и в некоторых родных диалогах, таких как QFileDialog. Важно, чтобы вы создавали эти пункты меню с стандартными сочетаниями клавиш, чтобы соответствующие функции редактирования были включены в диалогах. В настоящее время нет MenuRole идентификаторов для них, но они будут автоматически определяться так же, как и элементы меню приложения, когда QAction имеет значение по умолчанию TextHeuristicRole.

Специальные клавиши

Для обеспечения ожидаемого поведения приложений Qt на macOS значения перечисления Qt::Key_Meta, Qt::MetaModifier и Qt::META соответствуют клавишам Control на стандартной клавиатуре Apple, а значения перечисления Qt::Key_Control, Qt::ControlModifier и Qt::CTRL соответствуют клавишам Command.

Панель задач

Взаимодействие с панелью задач возможно. Иконка может быть установлена путём вызова QWindow::setWindowIcon() из главного окна вашего приложения. Вызов setWindowIcon() может быть произведён столько раз, сколько необходимо, для обновления иконки.

Доступность

Многие пользователи взаимодействуют с macOS с помощью вспомогательных устройств. Цель Qt — сделать это автоматически в вашем приложении, чтобы оно соответствовало принятой практике на этой платформе. Qt использует фреймворк доступности Apple для обеспечения доступа пользователям с ограниченными возможностями.

Поддержка библиотек и развертывания

Qt поддерживает такие структуры macOS, как Frameworks и пакеты. Важно знать о этих структурах, поскольку они напрямую влияют на развертывание приложений.

Qt предоставляет инструмент для развертывания macdeployqt, чтобы упростить процесс развертывания. Статья Qt для macOS — Развертывание более подробно описывает процесс развертывания.

Библиотеки Qt в качестве Frameworks

По умолчанию Qt собирается как набор Frameworks. Frameworks — предпочтительный способ распространения библиотек на macOS. На сайте Руководство по программированию Frameworks Apple представлена более подробная информация о Frameworks.

Важно помнить, что Frameworks всегда связываются с релизными версиями библиотек. Если требуется отладочная версия Qt Framework, используйте переменные среды DYLD_IMAGE_SUFFIX, чтобы гарантировать загрузку отладочной версии:

export DYLD_IMAGE_SUFFIX=_debug

В качестве альтернативы, вы можете временно поменять свои отладочные и релизные версии, что описано в техническом примечании Apple «Debugging Magic».

Если вы не хотите использовать Frameworks, просто настройте Qt с -no-framework.

./configure -no-framework

Библиотеки, основанные на пакетах

Если вы хотите использовать некоторые динамические библиотеки в пакете приложения macOS (каталоге приложения), создайте подкаталог Frameworks в каталоге пакета приложения и поместите туда свои динамические библиотеки. Приложение найдёт динамическую библиотеку, если у неё есть имя установки @executable_path/../Frameworks/libname.dylib.

Если вы используете qmake и Makefiles, используйте настройку QMAKE_LFLAGS_SONAME:

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

В качестве альтернативы, вы можете изменить имя установки, используя install_name_tool(1) в командной строке.

Переменная среды DYLD_LIBRARY_PATH переопределит эти настройки и любые другие стандартные пути, такие как поиск динамических библиотек внутри /usr/lib и аналогичных стандартных расположений.

Если вы используете старые версии GDB, вы должны запускать его с полным путём к исполняемому файлу. Более поздние версии позволяют передать имя пакета в командной строке.

Объединение библиотек

Если вы хотите создать новую динамическую библиотеку, объединяющую динамические библиотеки Qt 4, вам нужно добавить флаг ld -r. Затем информация о релокации хранится в выходном файле, так что этот файл может быть объектом последующего выполнения ld. Это делается путём установки флага -r в файле .pro и настройках LFLAGS.

Порядок инициализации

dyld(1) вызывает глобальные статические инициализаторы в порядке их подключения к приложению. Если библиотека связывается с Qt и ссылается на глобальные переменные в Qt (из глобальных инициализаторов в вашей собственной библиотеке), свяжите приложение с Qt до связывания его с библиотекой. В противном случае результат будет неопределённым, так как глобальные инициализаторы Qt ещё не были вызваны.

Флаги времени компиляции

Следующие флаги полезны, когда вы хотите определить код, специфичный для macOS:

  • Q_OS_DARWIN определён, когда Qt обнаруживает, что вы работаете на системе на основе Darwin, такой как macOS или iOS.
  • Q_OS_MACOS определён, когда вы работаете на системе macOS.

Примечание: Q_WS_MAC больше не определён в Qt 5.

Если вы хотите определить код для конкретных версий macOS, используйте макросы доступности, определённые в /usr/include/AvailabilityMacros.h.

В документации QSysInfo есть информация о проверке версии во время выполнения.

Доступ к родным API macOS

Доступ к пути пакета

Приложения macOS структурированы как каталог (заканчивающийся .app). Этот каталог содержит подкаталоги и файлы. Может быть полезно разместить элементы, такие как плагины и документацию онлайн, внутри этого пакета. Следующий код возвращает путь к пакету приложения:

#ifdef Q_OS_MAC
    CFURLRef appUrlRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
    CFStringRef macPath = CFURLCopyFileSystemPath(appUrlRef,
                                           kCFURLPOSIXPathStyle);
    const char *pathPtr = CFStringGetCStringPtr(macPath,
                                           CFStringGetSystemEncoding());
    qDebug("Path = %s", pathPtr);
    CFRelease(appUrlRef);
    CFRelease(macPath);
#endif

Примечание: Когда в macOS установлен японский язык, ошибка приводит к тому, что эта последовательность завершается неудачно и возвращает пустую строку. Поэтому всегда проверяйте возвращённую строку.

Дополнительную информацию об использовании API CFBundle см. на сайте разработчиков Apple.

QCoreApplication::applicationDirPath() можно использовать для определения пути к исполняемому файлу в пакете.

Перевод меню приложения и системных диалогов

Элементы меню приложения будут корректно объединяться для локализованных приложений, но они не будут отображаться переведёнными до тех пор, пока пакет приложения не будет содержать папку с локализованными ресурсами. к пакету приложения.

По сути, нужен файл под названием locversion.plist. Вот пример приложения с норвежской локализацией:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>LprojCompatibleVersion</key>
    <string>123</string>
    <key>LprojLocale</key>
    <string>no</string>
    <key>LprojRevisionLevel</key>
    <string>1</string>
    <key>LprojVersion</key>
    <string>123</string>
</dict>
</plist>

После этого, при запуске приложения с предпочтительным языком норвежский, пункты меню должны отображаться как Avslutt вместо Quit.

Руководство по работе с пакетами содержит информацию о пакетах и папке локализованных ресурсов.

Использование Qt с нативным кодом

Для добавления нативных элементов управления Cocoa и представлений в приложение Qt или для интеграции Qt в нативное приложение Cocoa доступны два класса: QMacCocoaViewContainer и QMacNativeWidget.

Использование нативных панелей Cocoa

Диспечер событий Qt более гибкий, чем тот, который предлагает Cocoa, и позволяет пользователю запускать диспечер событий (и выполнять QEventLoop::exec) без необходимости учитывать, отображаются ли модальные диалоговые окна на экране (что отличается от Cocoa). Поэтому нам нужно выполнить дополнительное управление в Qt, чтобы обработать это должным образом, что, к сожалению, затрудняет смешение нативных панелей. На данный момент лучший способ сделать это – следовать приведенной ниже схеме, где высылается вызов функции с нативным кодом вместо прямого вызова. Тогда мы знаем, что Qt корректно обновил все ожидающие рекурсии цикла событий до отображения нативной панели:

#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();
}

Ограничения

MySQL и macOS

По-видимому, возникает проблема, когда оба -prebind и -multi_module определены при линковке статических C библиотек в динамические библиотеки. Если при линковке 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

перелинкуйте Qt с помощью -single_module. Эта проблема возникает только при построении драйвера MySQL в Qt. Она не влияет на плагины или статические сборки.

D-Bus и macOS

Модуль QtDBus по умолчанию динамически загружает библиотеку libdbus-1 на macOS. Это означает, что приложения, связанные с модулем QtDBus, будут загружаться даже на системах macOS, на которых отсутствуют библиотеки, но они не смогут подключиться к любому серверу D-Bus и не смогут открыть сервер с помощью QDBusServer.

Для использования функциональности D-Bus вам необходимо установить библиотеку libdbus-1, например, через Homebrew, Fink или MacPorts. Вы можете включить эти библиотеки в пакет приложения, если вы развертываете его на других системах. Кроме того, обратите внимание, что на macOS нет системного шины, и шина сеанса будет запущена только после того, как launchd будет настроен для ее управления.

Действия меню

  • Действия в QMenu с активаторами, имеющими более одной последовательности нажатий клавиш (QKeySequence), не будут отображаться корректно, когда QMenu переводится в нативное меню Mac. Будет отображена только первая клавиша. Однако, сочетание клавиш по-прежнему будет активировано на всех остальных платформах.
  • QMenu объекты, используемые в нативном меню, не могут обрабатывать события Qt через стандартные обработчики событий. Установите делегата на сам объект меню, чтобы получать уведомления об этих изменениях. В качестве альтернативы, рассмотрите использование сигналов QMenu::aboutToShow() и QMenu::aboutToHide() для отслеживания видимости меню; это обеспечивает решение, которое должно работать на всех платформах, поддерживаемых Qt.
  • По умолчанию Qt создаёт нативный пункт меню Выход, который реагирует на сочетание клавиш CMD+Q. Создание QAction для роли QAction::QuitRole заменит этот пункт меню. Поэтому действие замены должно быть подключено к слоту QCoreApplication::quit или к пользовательскому слоту, который завершает работу приложения.

Нативные виджеты

Qt поддерживает диалоговые окна, представленные флагом окна Qt::Sheet.

Обычно, когда речь идёт о нативном приложении macOS, нативное означает приложение, которое взаимодействует напрямую с базовой системой окон, а не с использованием какого-либо промежуточного слоя. Приложения Qt работают как полноправные пользователи, точно так же, как и приложения Cocoa. Мы используем Cocoa для взаимодействия с операционной системой внутри.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.14/macos-issues.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API