Qt for macOS - 特定の問題
このページでは、Qt の macOS サポートに関する主な問題を概説します。macOS の用語や具体的な処理については、https://developer.apple.com/ を参照してください。
アクア
Aquaスタイルは、macOSプラットフォームに欠かせないものです。Cocoaと同様に、QtはmacOSヒューマンインターフェースガイドラインに記述されているようなウィジェットを提供します。Qt のウィジェットはルック&フィールのために AppKit を使用していますが、個々の Qt ウィジェットをラップされたネイティブコントロールとして表現しているわけではないことに注意してください。
Qt Widget Galleryページには、macOS プラットフォームのテーマを使用したアプリケーションのサンプル画像があります。
macOS 用 Qt 属性
以下は、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 は常にスクリーンをダブルバッファリングするので、Qt::WA_PaintOnScreen 属性は効果がありません。また、ペイントイベントの外側でペイントすることは不可能なので、Qt::WA_PaintOutsidePaintEvent も効果がありません。
マウスの右クリック
QContextMenuEvent クラスは、macOS アプリケーションの右マウスクリックをサポートします。これはコンテキストメニューイベントにマッピングされます。これはマウスの右クリックの最も一般的な使い方で、macOSのワンボタンマウスサポートではコントロールクリックにマッピングされます。
国際化
macOSのアプリケーションは、アプリケーションのInfo.plist
の一部として、サポートする言語を宣言します。システムは、アプリケーションのサポート言語とユーザーの言語設定を照合し、アプリケーションが起動するロケールを決定します。これにより、QLocale::uiLanguages ()を通じて反映される順序付けられた言語が決定され、AppKitなどのシステムフレームワークが、メニュータイトルや文字列などのローカライズされたリソースをどのようにピックアップするかが決定されます。
Qt アプリは最初から翻訳されているわけではないので、デフォルトで生成されるCMake
とqmake
プロジェクトのInfo.plist
は次のように設定されています。 CFBundleAllowMixedLocalizations
をYES
に設定します。これは、システムフレームワークがユーザーの言語設定に最も合うローカライズを選択できるようにするためです。qt_add_translations を使ってアプリケーションに翻訳を追加すると、qt_add_translations の CFBundleAllowMixedLocalizations
キーは自動的に削除され CFBundleLocalizations
に置き換わります。qmake
では、このプロセスは手動で行う必要があります。
メニューバー
Qt はメニューバーを検出し、Mac ネイティブのメニューバーに変換します。これを既存の Qt アプリケーションに組み込むのは、通常は自動的です。しかし、特別なニーズがある場合、Qtの実装は現在、Activeなウィンドウ(例えば、QGuiApplication::focusWindow())から開始し、以下のテストを適用することでメニューバーを選択します:
- ウィンドウにQMenuBar があれば、それが使われます。
- ウィンドウがモーダルの場合、そのメニュー・バーが使用されます。メニュー・バーが指定されていない場合、デフォルトのメニュー・バーが使用されます(以下に記述します)。
- ウィンドウが親を持たない場合、デフォルトのメニューバーが使用される(以下で説明する)。
これらのテストは、上記のルールのいずれかが満たされるまで、親ウィンドウの連鎖の上まで続きます。すべてが失敗した場合、デフォルトのメニューバーが作成されます。Qt のデフォルトのメニューバーは空のメニューバーです。しかし、親のないQMenuBar を作成することで、別のデフォルト・メニュー・バーを作成することができます。最初に作成されたものがデフォルトのメニュー・バーとなり、デフォルトのメニュー・バーが必要になったときに使用されます。
ネイティブ・メニュー・バーの使用は、Qt クラスに特定の制限をもたらします。以下の制限事項のセクションに、より詳細な情報があります。
Qt は、QMenuBar でグローバルメニューバーのサポートを提供しています。 macOS のユーザーは、画面の上部にメニューバーがあることを期待しており、Qt はこれに対応しています。
例えば、アプリケーションメニューには「バージョン情報」、「環境設定」、「終了」などが含まれます。Qtは、アプリケーションメニューと直接対話する手段を提供しませんが、これらの規約を処理します。
各QAction には、アプリケーションメニュー項目の特別な配置を制御するmenuRole プロパティがあります。しかし、デフォルトではmenuRole
はTextHeuristicRole になっており、メニュー項目はtext によって自動検出されます。
Cut、Copy、Paste、Select Allのような他の標準的なメニュー項目は、あなたのアプリケーションでも、QFileDialog のようないくつかのネイティブダイアログでも適用できます。これらのメニュー項目を標準ショートカットで作成し、対応する編集機能がダイアログで有効になるようにすることが重要です。現時点ではMenuRole
の識別子はありませんが、QAction
にデフォルトのTextHeuristicRole が設定されている場合、アプリケーションのメニュー項目と同様に自動検出されます。
特殊キー
macOS 上の Qt アプリケーションに期待される動作を提供するために、Qt::Key_Meta 、Qt::MetaModifier 、Qt::META の列挙値は標準の Apple キーボードの Control キーに対応し、Qt::Key_Control 、Qt::ControlModifier 、Qt::CTRL の列挙値は Command キーに対応します。
ドック
ドックとのインタラクションが可能です。アプリケーションのメイン・ウィンドウからQWindow::setWindowIcon()を呼び出すことで、アイコンを設定できます。setWindowIcon()は何度でも呼び出すことができ、簡単に更新できるアイコンを提供します。
アクセシビリティ
多くのユーザは、補助デバイスを使って macOS を操作します。Qt の目的は、アプリケーションのアクセシビリティを自動化することです。Qt は Apple のアクセシビリティ・フレームワークを使用し、障害のあるユーザーへのアクセスを提供します。
ライブラリとデプロイのサポート
Qt は、Frameworks や bundles といった macOS の構造をサポートしています。これらの構造はアプリケーションのデプロイに直接影響するため、認識しておくことが重要です。
Qt はデプロイツールmacdeployqt を提供し、デプロイプロセスを簡素化します。Qt for macOS - Deploymentの記事で、デプロイプロセスの詳細を説明しています。
フレームワークとしての Qt ライブラリ
デフォルトでは、Qt はフレームワークとしてビルドされています。フレームワークは macOS が推奨するライブラリの配布方法です。Appleのフレームワークプログラミングガイドのサイトには、フレームワークについてより多くの情報があります。
フレームワークは常にリリースバージョンのライブラリとリンクすることを覚えておくことが重要です。Qt フレームワークのデバッグバージョンが必要な場合は、DYLD_IMAGE_SUFFIX
環境変数を使用して、デバッグバージョンがロードされるようにしてください:
export DYLD_IMAGE_SUFFIX=_debug
あるいは、デバッグ版とリリース版を一時的に入れ替えることもできます。これはApple の "Debugging Magic" テクニカルノートに記載されています。
フレームワークを使いたくない場合は、-no-framework
で Qt を設定するだけです。
./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内のダイナミック・ライブラリの検索や同様のデフォルトの場所など、その他のデフォルトのパスを上書きします。
ライブラリの組み合わせ
Qt ダイナミック・ライブラリを組み合わせて新しいダイナミック・ライブラリをビルドしたい場合は、ld -r
フラグを導入する必要があります。そうすると、リロケーション情報が出力ファイルに保存され、このファイルを別のld
。このためには、.pro
ファイルに-r
フラグを設定し、LFLAGS
の設定を行います。
初期化の順序
dyld(1)
は、アプリケーションにリンクされた順に、グローバルな静的イニシャライザを呼び出します。ライブラリが Qt とリンクし、Qt のグローバルを(自分のライブラリのグ ローバル初期化子から)参照する場合は、ライブラリをリンクする前にアプリケーション を Qt とリンクしてください。そうしないと、Qt のグローバル・イニシャライザがまだ呼び出されていないため、結果は未定義になります。
コンパイル時のフラグ
以下のフラグは、macOS特有のコードを定義したい場合に役立ちます:
Q_OS_DARWIN
は、macOS や iOS のような Darwin ベースのシステムを使用していることを Qt が検出したときに定義されます。Q_OS_MACOS
は、macOS システムを使用しているときに定義されます。
注意: Q_WS_MAC
は Qt 5 以降では定義されなくなりました。
特定のバージョンの macOS 用のコードを定義したい場合は、/usr/include/AvailabilityMacros.h で定義されているアベイラビリティマクロを使用してください。
QSysInfo と QOperatingSystemVerison のドキュメントに、実行時のバージョンチェックに関する情報があります。
macOSネイティブAPIアクセス
バンドルパスへのアクセス
macOSアプリケーションはディレクトリ(末尾は.app)で構成されています。このディレクトリにはサブディレクトリとファイルが含まれています。プラグインやオンラインドキュメントなどのアイテムをこのバンドルの中に置くと便利です。以下のコードはアプリケーションバンドルのパスを返します:
#ifdef Q_OS_MAC QStringbundlePath=QString::fromNSString(NSBundle.mainBundle.bundlePath); qDebug() << "Bundle path =" << bundlePath; #endif
NSBundle APIの使用に関する詳細は、Appleのデベロッパーウェブサイトをご覧ください。
QCoreApplication::applicationDirPath() は、バンドル内のバイナリのパスを決定するために使用できます。
ネイティブ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
静的 C ライブラリを動的ライブラリにリンクする際、-prebind
と-multi_module
の両方が定義されている場合に問題があるようです。Qt.MySQLをリンクする際に以下のようなエラーメッセージが表示されます:
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
single_moduleを使用してQtを再リンクしてください。これは MySQL ドライバを Qt にビルドするときだけの問題です。プラグインや静的ビルドには影響しません。
D-Bus と macOS
QtDBus モジュールは、macOS 上で libdbus-1 ライブラリを動的にロードするようにデフォルト設定されています。つまり、QtDBus モジュールに対してリンクするアプリケーションは、ライブラリを持たない macOS システムでもロードされますが、D-Bus サーバーへの接続に失敗し、QDBusServer を使用してサーバーを開くことに失敗します。
D-Busの機能を使うには、Homebrew、Fink、MacPortsなどでlibdbus-1ライブラリをインストールする必要がある。他のシステムにデプロイする場合は、これらのライブラリをアプリケーションのバンドルに含めるとよいでしょう。さらに、macOSにはシステムバスがなく、セッションバスはlaunchdがそれを管理するように設定された後にのみ起動することに注意してください。
メニューアクション
- アクセラレータを使用したQMenu で、複数のキーストロークを持つアクション (QKeySequence) は、QMenu が Mac ネイティブのメニューバーに変換されると、正しく表示されません。最初のキーが表示されます。しかし、ショートカットは他のすべてのプラットフォームと同様に有効になります。
- QMenu ネイティブメニューバーで使用されているオブジェクトは、通常のイベントハンドラで Qt イベントを処理することができません。メニュー自体にデリゲートを設置して、これらの変更を通知するようにしてください。あるいは、 () と () シグナルを使用して、メニューの可視性を追跡することを検討してください。これらは、Qt がサポートするすべてのプラットフォームで動作するソリューションを提供します。QMenu::aboutToShow QMenu::aboutToHide
- デフォルトでは、Qt は
CMD+Q
ショートカットに反応するネイティブのQuitメニュー項目を作成します。QAction::QuitRole の役割のためにQAction を作成すると、そのメニュー項目は置き換えられます。したがって、置き換えアクションは、QCoreApplication::quit スロットか、アプリケーションを停止するカスタムスロットのいずれかに接続する必要があります。
ネイティブウィジェット
Qt は、ウィンドウフラグQt::Sheet で表されるシートをサポートしています。
通常、macOSのネイティブ・アプリケーションを指す場合、ネイティブとは、中間レイヤーを使用するアプリケーションではなく、基礎となるウィンドウ・システムに直接インターフェイスするアプリケーションを意味します。Qtアプリケーションは、Cocoaアプリケーションと同様に、第一級市民として実行されます。オペレーティング・システムとの通信には、内部的にCocoaを使用しています。
シンボルの可視性に関する警告
C++ライブラリのリンクでは、関数やオブジェクトはシンボルと呼ばれます。シンボルには、default
またはhidden
の可視性があります。
パフォーマンス上の理由から、Qt や他の多くのライブラリは、デフォルトでhidden
の可視性を使用してソースをコンパイルし、ユーザープロジェクトで使用する場合にのみ、シンボルにdefault
の可視性を付けます。
残念ながら、あるライブラリがhidden
でコンパイルされ、ユーザープロジェクトのアプリケーションやライブラリがdefault
でコンパイルされると、Apple のリンカーは警告を出すことがあります。
プロジェクト開発者が警告を消したい場合は、プロジェクト・コードもhidden
でコンパイルする必要があります。
CMakeでは、以下のコードをCMakeLists.txt
に追加することで、これを行うことができます:
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
qmakeでは、.pro
ファイルに以下のコードを追加することで可能です:
CONFIG+=hide_symbols
プロジェクトがライブラリをビルドする場合、ライブラリのシンボルが他のライブラリやアプリケーションで使用されることを意図している場合は、default
visibilityを明示的にマークする必要があります。例えば、そのような関数やクラスには、Q_DECL_EXPORT のアノテーションを付けてください。
CMake Xcode プロジェクトで作成された xcarchive に dSYM バンドルがありません。
Xcode のバグと特定のCMake の制限により、CMake で生成された Xcode プロジェクトは、Xcode のアーカイブタスク中に、アプリケーションのdSYM
バンドルをxcarchive
にインクルードすることに失敗します。
Qt は、dSYM
バンドルがxcarchive
に含まれるように、オプトインとして回避策を提供しますが、それにはトレードオフが伴います。つまり、以下のCMake機能は正しく動作しません:
$<TARGET_FILE:app>
ジェネレータ式が、アプリのバイナリにつながらない無効なパスに展開される可能性があります。CMAKE_RUNTIME_OUTPUT_DIRECTORY
変数とそれに関連するRUNTIME_OUTPUT_DIRECTORY
ターゲットプロパティは、設定されていても無視されます。- その他の未知の問題
上記の問題を軽減するには、以下の方法があります:
- プロジェクトの開発中ではなく、
xcarchive
を作成する場合にのみ回避策を有効にする。 - プロジェクトのルート・ディレクトリにのみ実行可能ファイルとライブラリを追加し、
add_subdirectory
の呼び出しには追加しない。
回避策を有効にするには、以下のオプションを使用してプロジェクトを構成します:
cmake . -DQT_USE_RISKY_DSYM_ARCHIVING_WORKAROUND=ON
または、qt_add_executable
または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.