1

ユーザー アクションが各ランタイムでアプリケーション データを初期化する場合のユース ケースがあります。ここでその動作を表すのが私のサンプル コードです。

SignalSlotChange.h

#ifndef SIGNALSLOTCHANGE_H
#define SIGNALSLOTCHANGE_H

#include <QtGui>

class SignalSlotChange : public QWidget
{
Q_OBJECT

public:
    SignalSlotChange(QWidget *parent = 0);

private slots:
    void firstCall();
    void secondCall();

private:
    QPushButton *button;

};

#endif // SIGNALSLOTCHANGE_H

SignalSlotChange.cpp

#include "SignalSlotChange.h"

SignalSlotChange::SignalSlotChange(QWidget *parent) : QWidget(parent)
{
    button = new QPushButton("Messgage", this);
    QObject::connect(button, SIGNAL(clicked()), this, SLOT(firstCall()));
    show();
}

void SignalSlotChange::firstCall()
{
    QMessageBox::information(this, "SignalSlotChange", "First call", QMessageBox::Ok, QMessageBox::NoButton);
    // Change the signal-slot connection to secondCall()
    QObject::disconnect(button, SIGNAL(clicked()), this, SLOT(firstCall()));
    QObject::connect(button, SIGNAL(clicked()), this, SLOT(secondCall()));
}

void SignalSlotChange::secondCall()
{
    QMessageBox::information(this, "SignalSlotChange", "Second call", QMessageBox::Ok, QMessageBox::NoButton);
}


int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    SignalSlotChange ssc;
    return app.exec();
}

ボタンが押されると、初期化スロットfirstCall()が呼び出されます。secondCall()後続の信号用に信号スロット接続を変更しました。

私が行う方法の問題は、それが高度に結合されており、スロットが正確な方法とそれを変更するための信号を知っている必要があることです。

を使用QObject::sender()すると、送信者の発信元はわかりますが、その信号はわかりません。たまたまその信号を発信した送信者は 1 つだけです。

ブール値でそれを行うことができますが、first_callそれは後続のすべての呼び出しのブール値をチェックすることになります。これは避けたいものであり、したがってこの質問です。

4

1 に答える 1

1

メンバーへのポインターのアプローチを使用して、多少異なるソリューションを実装できます。

SignalSlotChange.h

#ifndef SIGNALSLOTCHANGE_H
#define SIGNALSLOTCHANGE_H

#include <QtGui>

class SignalSlotChange : public QWidget {
Q_OBJECT


public:
    SignalSlotChange(QWidget *parent = 0);

private slots:
    void callCall();

private:
    void (SignalSlotChange::* delegate) (); 

    void firstCall();
    void secondCall();

    QPushButton *button;

};

#endif // SIGNALSLOTCHANGE_H

SignalSlotChange.cpp

#include "SignalSlotChange.h"

SignalSlotChange::SignalSlotChange(QWidget *parent) : QWidget(parent) {
    delegate = &SignalSlotChange::firstCall;

    button = new QPushButton("Messgage", this);
    QObject::connect(button, SIGNAL(clicked()), this, SLOT(callCall()));
    show();
}

void SignalSlotChange::callCall() {
    (this->*delegate) ();
}

void SignalSlotChange::firstCall() {
    QMessageBox::information(this, "SignalSlotChange", "First call", QMessageBox::Ok, QMessageBox::NoButton);

    // Change the effective signal-slot connection to secondCall()
    delegate = &SignalSlotChange::secondCall;
}

void SignalSlotChange::secondCall() {
    QMessageBox::information(this, "SignalSlotChange", "Second call", QMessageBox::Ok, QMessageBox::NoButton);
}


int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    SignalSlotChange ssc;
    return app.exec();
}

デカップリングの観点からこれがより良い解決策であるかどうかはわかりませんが、メカニズムが実際にトリガーされたスロットについて何も知る必要がないという利点があります。「メソッド スイッチ」を実装するための完全なロジックは、SignalSlotChangeクラス内にカプセル化されています。スロットはcallCall()他の互換性のある信号に接続でき、メソッド スイッチは引き続き機能し、コードを変更する必要はありません。

于 2012-12-03T15:04:19.273 に答える