Qt の QObject の基礎となるアーキテクチャと原則の詳細な説明

そもそもQTのQObjectとは何でしょうか?

Qobject は QT の基本クラスであり、すべての QT オブジェクトの親クラスであり、シグナルやスロット、属性システム、メタオブジェクト システムなどのいくつかの基本機能を提供します。クラスにこれらの関数を持たせたい場合は、クラスを Qobject から継承し、クラス宣言に Q_OBJECT マクロを追加する必要があります。このようにして、moc はクラスのメタオブジェクト コードを生成し、クラスが実行時に独自のメタ情報を取得できるようにします。

コードでは次のように記述します。

 Q_OBJECT を導入すると、定義されたクラス class が QObject を継承し、シグナルとスロット (最も使用されるメカニズム) を呼び出すことができるようになります。

Qobjectの公式の詳しい説明はこちら

ここで注意すべき点の 1 つは、QObject を使用したい場合は、ヘッダー ファイルを導入する必要があるということです。

#include <QObject>

この方法でのみ、connect()、disconnect() などの使い慣れたいくつかの一般的な関数を使用できます。

さらに、QObject は Qt オブジェクト モデルの中核です。モデルの中心的な機能は、シグナルとスロットと呼ばれるシームレスなオブジェクト通信のための非常に強力なメカニズムです。connect() を使用して信号をスロットに接続し、disconnect() を使用して接続を破棄できます。終わりのない通知ループを回避するには、blockSignals() を使用してシグナルを一時的にブロックします。保護された関数connectNotify()およびdisconnectNotify()。

さらに、私たちがよく使うように、

Q_INVOKABLE は C++ 関数を qml 呼び出しに公開し、Q_PROPERTY_AUTO は qml 呼び出しにパラメーターを定義します。これらはすべて QObject に基づいています。

Qobject は QT を記述するための重要な親クラスであることがわかります。また、オブジェクトが子オブジェクトを持つメカニズムであるメモリ管理メカニズムもあり、あるオブジェクトが別のオブジェクトの親になることができます。親オブジェクトが破棄されると、そのすべての子も破棄されます。これにより、メモリが乱用されることがなくなり、メモリを適切なタイミングで解放できるようになります。

また、オブジェクトが自身を記述するメカニズムであるイントロスペクション (Introspection) メカニズムにより、オブジェクトは自身のクラス名、継承関係、メソッド、属性、その他の情報を知ることができます。metaObject() 関数を使用すると、オブジェクトに関するメタオブジェクト情報を取得できます。Inherits () 関数を使用すると、 オブジェクトのクラスが QObject 継承階層内の別のクラスから継承しているかどうかを判断できます。オブジェクトが削除されると、  destroy () シグナルが発行されます。このシグナルをキャッチして、 QObjectsへのダングリング参照を回避できます  。

Qt は、メタ オブジェクト (メタ オブジェクト) を使用してイントロスペクション メカニズムを実装します。メタ オブジェクトは、オブジェクトのメタ情報を格納するオブジェクトであり、QObject::metaObject() 関数を通じて取得できます。Qt は MOC (Meta Object Compiler) を使用してメタオブジェクト コードを生成します。MOC は、Q_OBJECT マクロを含むクラスをスキャンし、対応するメタオブジェクト コードを生成するプリプロセッサです。メタオブジェクトを使用して、信号やスロット、動的プロパティ、動的呼び出しなどの機能を実装できます。

ここで、シグナルとスロットの役割について詳しく説明します。

Qのシグナルとスロットは、ボタンをクリックしてウィンドウを閉じるなど、コントロール間のインタラクティブな操作を実現するオブジェクト間通信の仕組みです。シグナルとスロットは、任意の数とタイプのパラメータを伝送できる高レベルのインターフェイスです。シグナルとスロットは Q 固有のメッセージ送信メカニズムであり、moc と呼ばれる QT ツールを使用して正しく処理する必要があります。
シグナルは、ユーザーがウィンドウまたはコントロールに対して特定の操作を実行したことにより、ウィンドウまたはコントロールが特定のイベントを生成したときに、Q に対応するウィンドウ クラスがユーザーの操作に応答するために特定のシグナルを送信します。シグナルの表示形式は関数です。つまり、イベントが発生すると、Qt フレームワークは対応するシグナル関数を呼び出してユーザーに通知します。
スロットは関数関数の特別なクラスであり、クラスの通常のメンバー関数として使用でき、Q フレームで生成された信号を処理することもできます。特定のオブジェクトが特定の信号を送信していることが検出されると、その信号を処理するためにそれに接続されているスロット関数が呼び出されます。スロット関数は本質的にはコールバック関数であり、呼び出すタイミングはシグナル生成後であり、呼び出しはQtフレームワークによって実行されます。
Qobjectクラスのconnect関数でシグナルとスロットを接続し、バインディングを実現します。connect 関数は、シグナルを送信するオブジェクト、シグナル関数のアドレス、シグナルを受信するオブジェクト、およびスロット関数のアドレスを指定する必要があります。Connect 関数は、信号処理アクションを実行した登録信号とスロットに相当します。疎結合メカニズムです。信号を送信するオブジェクトは、信号を受信するオブジェクトが誰であるかを知りませんし、気にしません。信号は送信信号を知りませんし、誰の目的であるかを知りません。信号とスロットの署名が一致している限り、接続できます。Q のメタオブジェクト システムは、信号とスロット メカニズムの通常の動作を保証します。

QT のシグナルとスロットに関する簡単な例を次に示します。

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->closeBtn,&QPushButton::clicked,this,&MainWindow::close);
}

MainWindow::~MainWindow()
{
    delete ui;
}

簡単な例としては、クリックするとウィンドウを閉じるボタンを作成することが挙げられます。まず、closeBtn という名前のボタンを UI に追加する必要があります。次に、Mainwindow.cpp ファイルで、connect 関数を使用して、ボタンのクリック信号をウィンドウのスロットを閉じる関数に接続します。このようにして、ユーザーがボタンをクリックすると、ウィンドウの閉じる機能がトリガーされてウィンドウが閉じられます。

別の例として、名前と性別の 2 つのプロパティを持つ QObject から継承した Person クラスがあると仮定すると、Q_PROPERTY マクロを使用してこれら 2 つのプロパティを宣言し、Q_ENUM マクロを使用して性別の列挙型を宣言できます。このようにして、MOC はこのクラスのメタ オブジェクトを生成し、メタ オブジェクトを通じてこのクラスのメタ情報を取得できます。次のとおりです。

  • metaObject()->className() 関数を使用してクラス名を取得し、「person」を返します。
  • metaObject()->propertyCount() 関数を使用してプロパティの数を取得し、2 を返します。
  • metaObject()->property(0) 関数を使用して最初のプロパティのメタ プロパティ (QMetaProperty) を取得し、次に name() 関数を使用してプロパティ名を取得し、「name」を返します。
  • metaObject()->enumeratorCount() 関数を使用して列挙型の数を取得し、1 を返します。
  • metaObject()->enumerator(0) 関数を使用して最初の列挙型のメタ列挙 (QMetaEnum) を取得し、次に keyCount() 関数を使用して列挙値の数を取得し、4 を返します。

また、QObjectを使用して、 event ()を通じて イベントを受信し、他のオブジェクトのイベントをフィルターすることもできます。詳細については、「installEventFilter ()」および 「eventFilter ()」を参照してください 。便利なハンドラー childEvent () を再実装して、子イベントをキャプチャできます。イベントは、オブジェクトが作成されたスレッドで配信されます。 詳細については、「 thread () での Qt とスレッドのサポート」を参照してください。スレッド アフィニティを持たない QObject ( thread () がゼロを返す) の場合、イベント処理はまったく実行されないことに注意してください。

moveToThread () 関数を使用して 、オブジェクトとその子のスレッド アフィニティを変更します (オブジェクトに親がある場合、オブジェクトは移動できません)。最後に、QObject は Qt での基本的なタイマー サポートも提供していることに言及する価値があります。

おすすめ

転載: blog.csdn.net/Helloorld_1/article/details/131894118