Qt5の信号とスロット

Qt5 alphaは光を見ました。 この記事では、取り組んだ機能の1つについて説明します。これは、信号とスロットの新しい構文です。

前の構文


これは通常、信号とスロットを接続する方法です。

connect(sender, SIGNAL(valueChanged(QString,QString)), receiver, SLOT(updateValue(QString)) ); 

実際、 SIGNALおよびSLOTマクロは引数を文字列に変換します。 次に、 QObject::connect()は、これらの行をmocユーティリティによってコンパイルされたイントロスペクションデータと比較します。

この構文の問題は何ですか?

一般にすべてがうまく機能するという事実にもかかわらず、まだいくつかの不便さがあります:


新しい構文:関数ポインターの使用


今後のQt5は代替構文をサポートします。 上記のアプローチに加えて、信号とスロットを接続するこの新しい方法を使用できます。

 connect(sender, &Sender::valueChanged, receiver, &Receiver::updateValue ); 

どちらが美しいかは好みの問題です。 しかし、新しいオプションに慣れるのは非常に簡単です。

次に、それがもたらす利点を検討します。

コンパイル時に確認する

シグナルまたはスロットの名前を間違えた場合、またはスロットの引数がシグナルの引数と一致しない場合、コンパイルエラーが発生します。 これにより、リファクタリング後の時間を節約できます。

さらに、 static_assert 、引数が一致しない場合やQ_OBJECTスキップされる場合に明確なエラーを表示するためstatic_assert使用されました。

引数型の自動キャスト

これで、typedefまたは名前空間の使用を恐れることなく、暗黙的なキャストが可能な場合、他の型の引数を受け入れるスロットに信号を接続できます。

次の例では、パラメーターとしてQStringを受け入れる信号をQVariantを受け入れるスロットに接続します。 QVariantQStringを受け入れる暗黙的なコンストラクタがあるため、これは問題なく機能します。

 class Test : public QObject { Q_OBJECT public: Test() { connect(this, &Test::someSignal, this, &Test::someSlot); } signals: void someSignal(const QString &); public: void someSlot(const QVariant &); }; 

信号を任意の機能に接続します

前の例でsomeSlotたように、 someSlotは、 slotなしの単純なパブリックメソッドとして宣言されました。 Qtはスロットを直接呼び出すことができ、このためにイントロスペクションを必要としなくなりました。 (信号にはまだ必要ですが)

しかし今では、sinalを任意の関数またはファンクターに接続することもできます。

 static void someFunction() { qDebug() << "pressed"; } // ... somewhere else QObject::connect(button, &QPushButton::clicked, someFunction); 

これは、boostまたはtr1 :: bindと組み合わせて非常に強力な機能になることができます。

C ++ 11の無名関数

以前に説明されたすべては、古いC ++ 98で動作します。 ただし、C ++ 11をサポートするコンパイラを使用する場合は、新しい言語機能を使用することを強くお勧めします。 ラムダ式は、少なくともMSVC 2010、GCC 4.5、clang 3.1でサポートされています。 最後の2つについては、フラグとして-std=c++0xを指定する必要があります。

これで、次のコードを記述できます。

 void MyWindow::saveDocumentAs() { QFileDialog *dlg = new QFileDialog(); dlg->open(); QObject::connect(dlg, &QDialog::finished, [=](int result) { if (result) { QFile file(dlg->selectedFiles().first()); // ... save document here ... } dlg->deleteLater(); }); } 

これにより、非同期コードの作成が非常に簡単になります。

Source: https://habr.com/ru/post/J141983/


All Articles