Mac OS X QSystemTrayIconのactivated()を受けたスロット延長でhide()するとクラッシュする件
環境:Mac OS X + Qt 5.3.2 QSystemTrayIconでQSystemTrayIconのactivated()シグナルを受けたスロットの延長でQSystemTrayIcon::hide()するとクラッシュする件。
なんっどやっても内部クラッシュするのでなんでだー!!ってなってたけど、Qt内部のバグによるもので、回避策を打たないと100%クラッシュします。例を挙げて解説します。
QSystemTrayIconをクリックしたら対象のアイコンを隠したい時があったので、以下のようにコードを書きました。まず
QSystemTrayIcon *systray = new QSystemTrayIcon(this); connect(systray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
こんな感じで普通にconnectします。で、スロットの方では以下のように
void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason){ switch (reason) { case QSystemTrayIcon::Trigger: case QSystemTrayIcon::DoubleClick: case QSystemTrayIcon::MiddleClick: systray->hide(); break; default: break; }
まあ、至って普通に見えますね。が、これを動作させると大体以下のような感じで落ちます。
Crashed Thread: 0 Dispatch queue: com.apple.main-thread Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: EXC_I386_GPFLT Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libqcocoa.dylib 0x0000000103f47787 -[QNSStatusItem triggerSelector:button:] + 71 1 libqcocoa.dylib 0x0000000103f472a5 -[QNSImageView mousePressed:button:] + 405 2 com.apple.AppKit 0x00007fff90b4150e -[NSWindow sendEvent:] + 6853 3 com.apple.AppKit 0x00007fff90f2b29e -[NSStatusBarWindow sendEvent:] + 67 4 com.apple.AppKit 0x00007fff90b3d644 -[NSApplication sendEvent:] + 5761 5 libqcocoa.dylib 0x0000000103f22b0e -[QNSApplication sendEvent:] + 78 6 com.apple.AppKit 0x00007fff90a5321a -[NSApplication run] + 636 7 libqcocoa.dylib 0x0000000103f1f1d4 QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 2420 8 QtCore 0x000000010096bacd QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) + 381 9 QtCore 0x000000010096f007 QCoreApplication::exec() + 359 10 TEDT.RapidCopy 0x0000000100005bcc main + 236 11 TEDT.RapidCopy 0x00000001000057c4 start + 52
解決法は以下のようにすればokです。
void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason){ switch (reason) { case QSystemTrayIcon::Trigger: case QSystemTrayIcon::DoubleClick: case QSystemTrayIcon::MiddleClick: //Mac OS XのQtバグ回避 QMetaObject::invokeMethod(systray, "hide", Qt::QueuedConnection); break; default: break; } }
この現象はmacosxのバグとのことで、Qt4.xからずっと対処されていない問題のようです。
Qtをお使いの方ならご存知、何でも答えてくれるVokerさんが答えてくれています。
QSystemTrayIcon hide() crash on mac while I use QTimer to change the icon of QSystemTrayIcon | Qt Project forums | Qt Projectで、ちょっとつらいのがこの問題、Qt4.xのドキュメントには補足されてます。
QSystemTrayIcon Class Reference | Documentation | Qt Project
が、Qt5では補足が引き継がれていません。。
QSystemTrayIcon Class | QtWidgets 5.3 | Documentation | Qt Project
Qt5の補足にコピペで書いておいてあげないとと思ったのですが、投稿の仕方がわからず(´・ω・`)
誰か投稿の仕方教えてください。。
落ち方をぐぐってこの記事にたどり着く人が出たらいいなあと思ってます。
めっちゃわからずにはまったよー(´;ω;`)
2014/11/24訂正:
日本qtユーザー会の
Tasuku Suzuki (@task_jp) | Twitterさんからqtのバグであること、
またバグ回避方法のオススメについて教えて頂いたので、記事内容を訂正しました。
ありがとうございます(._.)
qtbugレポートへのリンクは以下の通りです。
https://bugreports.qt-project.org/browse/QTBUG-6328