3

最近 Qt を使い始めたので、シグナル/スロット メカニズムについて明確にする必要があります。GUI と、別のスレッドに存在するオブジェクト間の通信のための優れたツールであることは理解していますが、次のような単純なケースで使用する必要があるかどうかはよくわかりません。

私は 3 つのクラスを持っています。それらを MainWindow、DataManager、および DataWorker と呼びましょう。DataWorker は別のスレッドに存在し、新しいデータを収集する準備ができたときに通知します。その後、いくつかの処理の後、MainWindow ウィジェットで視覚化されます。GUI クラスを処理コードで汚染しないように DataManager クラスを作成しました。

では、DataManager と MainWindow の間の通信をどのように処理すればよいでしょうか。


オプション #1 - MainWindow へのポインターをメンバーとして持ち、そのメソッドを呼び出すだけ

class MainWindow
{
private:
    DataManager* dm;

public:
    MainWindow() : dm(new DataManager(this)) { }
    displayData(const char* processedData);
}

class DataManager : QObject
{
private:
    MainWindow *mw;

private slots;
    eventNewData()
    {
        // get and process the data
        mw = this->QObject.parent();
        mw->displayData(const char* processedData);
        // release data
    }
}

オプション #2 - MainWindow スロットを呼び出す新しいデータを通知する

class MainWindow
{
private:
    DataManager* dm;

private slots:
    displayData(const char* processedData);

public:
    MainWindow() : dm(new DataManager(this)) { QObject::connect(dm, SIGNAL(newData(const char*)), this, SLOT(displayData(const char*)); }

};

class DataManager : QObject
{    
signals:
    newData(const char* processedData);

private slots;
    eventNewData()
    {
        // get and process the data
        emit newData(processedData);
        // release data
    }
}

オプション 1 はより直感的に思えますが、Qt についてはよくわかりません。newData() シグナルに反応させたいクラスがさらにある場合、シグナルとスロットを使用する利点が分かります。

では、どちらがより良いオプションであり、2 つの間にパフォーマンスの違いはありますか?

4

3 に答える 3

3

最初のオプションは、信号/スロットメカニズムを使用するよりも優れたパフォーマンスを提供しますが、との間に密結合があるという欠点もありMainWindow ますDataManager。両者はお互いを知っているので、実際に別々に使用することはできません。それだけで、コードをリファクタリングする理由になっているはずです。

とは言うものの、3番目のオプションとして、MainWindow信号を受信したスロットをDataWorker使用DataManagerして、データをの使用可能な形式に変換するだけのヘルパークラスにすることができますMainWindow

class MainWindow
{
private:
    DataManager* dm;

public:
    MainWindow() : dm(new DataManager()) { }
    displayData(QString processedData);
private slots;
    eventNewData()
    {
        // get the data
        QString processedData = dm->preprocessData(data);
        displayData(processedData);
        // release data
    }
};

class DataManager
{
public:
    QString preprocessData(...);
};
于 2012-11-13T15:33:34.043 に答える
3

スレッドから GUI 関数を直接呼び出すことはできません。したがって、DataWorker と DataManager::eventNewData() の間にシグナル/スロット接続がない限り、オプション #1 は機能しません。別のスレッドから GUI 関数を呼び出す唯一の方法は、シグナル/スロット接続を使用することです。

シグナル/スロット通信は、純粋に実行時ベースであり、文字列で動作するため、常にオーバーヘッドが発生します (スロットの名前はコンパイル時に生成され、実行時に比較されます)。これは動的ディスパッチです。直接関数呼び出しは常に高速です。

答えは簡単です。信号が必要ない場合は、使用しないでください。この特定のケースでは、必要なのは MainWindow::displayData() を呼び出すことだけなので、DataManager と MainWindow 間の通信には必要ないように見えます。それを動的に変更して別の関数を呼び出す必要はないようです。シグナルとスロットは、スレッド間通信と配電盤のような接続を提供するためにあります。どちらも必要ない場合は、シグナルを使用する必要はありません。

于 2012-11-13T14:38:32.333 に答える
0

QT がどのように機能するのか正確にはわからないので、パフォーマンスに影響があるかどうかはわかりませんが、私の直感では、1. 大きな違いはないはずです 2. GUI コンテキストではおそらく問題にならないでしょう。

標準の QT メカニズムを使用するオプションには、DataManager が GUI について何も知る必要がないという利点があります。内部を変更せずに GUI を置き換えることができるため、多くの人がこの優れた設計を検討しています。

于 2012-11-13T14:50:02.633 に答える