nativeEventFilter ってどうやってハンドルするの?
Windowsで、ウィンドウメッセージ (WM_KEYDOWN とか) みたいなネイティブメッセージをハンドルしたい時、どうするのか調べてみました。nativeEventFilter( ... ) を TMainWindow や QApplication でオーバーライドしてもメッセージが飛んでこなかったので挫折しそうになりましたが、こちらを参考にしたら上手く行きました。
http://www.qtcentre.org/threads/56438-help-with-QAbstractNativeEventFilter
よく理解してなくて申し訳ないですが、念のためコードをメモっときます。
mainwindow.h
#include <QAbstractNativeEventFilter> class usbworker : public QAbstractNativeEventFilter { public: usbworker(); virtual bool nativeEventFilter( const QByteArray &eventType, void *message, long *result ); }; MainWindow に usbworker usb; プロパティを追加
mainwindow.cpp
usbworker::usbworker() { } bool usbworker::nativeEventFilter( const QByteArray &eventType, void *message, long *result ) Q_DECL_OVERRIDE { qDebug("i came here"); if (eventType == "windows_generic_MSG") { MSG *msg = static_cast<MSG *>(message); if (msg->message == WM_KEYDOWN) { // キーボード押したら飛んでくる return false; } } return false; }
Qt5.3.0 (Windows) の TabletEvent がおかしい
Qtではペンタブレットの使用時、
- QEvent::TabletEnterProximity (ペンを認識した)
- QEvent::TabletLeaveProximity (ペンを認識できなくなった)
というイベントが発生しますが、Qt5.3.0 (Windows) だと、QEvent::TabletLeaveProximity が発生しません。QEvent::TabletEnterProximity は発生してます。これは致命的です。Macでは問題なさそうな気がします(追っかけてはいませんが)。どうしよう…。
補足
Qt5.2.1でもダメでした…。
補足2
Qt5.3.0 (Mac) だと、QEvent::TabletLeaveProximity は来ました。
Qt5.3.0 (Mac版) で、単体キーのショートカットを受け付けない
FireAlpacaでは、前景色・背景色の入れ替えを、Xキーに割り当てています。
ui->action_Hoge->setShortcut( tr("X") ); ui->action_Hoge->setShortcut( QKeySequence( Qt::Key_X ) ); // これもダメ
Qt4.7までは、Windows版もMac版も上手く動作していました。
が、Qt5.3.0 (Qt5.2.1でも) だと、Mac版でイベントを受け付けなっています (Windows版はOK)。
画面上のウィジェットのコントロール (RGBの数値のQLineEditとか) が悪さしてるのかも…?
ui->action_Hoge->setShortcuts( QKeySequence::Undo );
ui->action_Hoge->setShortcut( tr("Ctrl+L") );
などは問題なく受け付けます。
補足
https://bugreports.qt-project.org/browse/QTBUG-38256
バグレポートにも上がってるようです。凄腕Macプログラマのみんな…助けて!
pthreadの代わりに、QtConcurrentRunを使う
pthreadを使う方法が分からなかったんですが、「QtConcurrentを使うと良い」というアドバイスを頂いたので、試してみました(実戦投入はまだです)。Debugモードじゃないと最適化されて一瞬で終わる模様。
#include <QtConcurrentRun> #include <QElapsedTimer> struct TParam { int threadIndex; int value; }; // テストしたマシンでは、約1000ms void thread_func( TParam* param ) { int sum = 0; for (int i=0; i<10000000; i++) { for (int j=0; j<45; j++) sum += 1; } param->value = param->threadIndex; param->value += sum; }
スレッド処理したい関数と、関数に渡したいパラメータを定義します。
QElapsedTimer et; et.start(); // 最大スレッド数 const int threadNum = 16; TParam param[threadNum]; for (int i=0; i<threadNum; i++) { param[i].threadIndex = i; param[i].value = 0; } #if 1 // 1〜4、どれにしても同じ時間かかる (8だと2倍、12だと3倍 (4スレッドマシンなので)) const int processNum = 4; QFuture<void> future[threadNum]; for (int i=0; i<processNum; i++) { future[i] = QtConcurrent::run( &thread_func, ¶m[i] ); } for (int i=0; i<processNum; i++) { future[i].waitForFinished(); } #else // 4倍処理に時間がかかる const int processNum = 4; for (int i=0; i<processNum; i++) { thread_func( ¶m[i] ); } #endif qint64 t = et.elapsed(); setWindowTitle( QString::number( param[3].value ) ); setWindowTitle( QString::number(t) );
pthreadで言うところの "pthread_join" が waitForFinished に相当するようです。概ね想像通りの処理時間になっているので、恐らく正しく動作しているのでしょう。
Qt4.8.4 の tabletEvent (Mac版)
Qt4.8.4 (Mac版) では、Qt4.7.4 では飛んでくる QWidget::tabletEvent が飛んで来ません。どうやら放置されてるようですね……困った(涙)。
QWebView が止まらない
QUrl url( "http://www.google.co.jp" ); QWebView* view = new QWebView(); view->setUrl( url ); delete view;
というコードでQWebViewを作成・削除すると、バックグラウンドでネットワーク関連のレジストリにアクセスをし続けます (Process Monitor - Sysinternals で確認)。
http://technet.microsoft.com/ja-jp/sysinternals/bb842062.aspx (Sysinternals Suite
QWebView* view = new QWebView(); //view->setUrl( url ); delete view;
と、setUrlをコメントアウトすると、バックグランドの動作は行われません。これは、最初のコードだと QWebPage( view->page() ) が生き続けてるという事なんでしょうか? 完全に止める方法が分からず困っています…。
QtSDK 1.2.1 と macdeployqt
Kenjiさんにご指摘いただいた後で申し訳ないのですが、QtSDK 1.2.1 (Qt4.8.1) が公開されていたので、Mac版を試してみました。QtDesktopで問題なくビルドできたのは良かったんですが、やはりビルドして macdeployqt したアプリケーションが Leopard で起動できない事が確認できました。Lionだと動くんですが......。
ちなみに、Leopardでのレポートは、こんな感じです。
Dyld Error Message: Symbol not found: _OBJC_CLASS_$_CALayerHost Referenced from: /Users/xxxxx/Desktop/XxxxXxxx.app/Contents/MacOS/../Frameworks/QtWebKit.framework/Versions/4/QtWebKit Expected in: /System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore
QtSDK 1.1.3 で生成したアプリだと、問題なく起動します。