1

これは、基になる変数に変更を書き込むSpinBoxのサンプルです。私が抱えている主な問題は、ウィジェットの構築時にvalueChangedが呼び出されることです。これを行うためのよりエレガントな方法はありますか?ウィジェットをそれ自体に接続したのは奇妙だと思いますが、valueChangedは仮想ではありません。

class ValueWriterInt: public QSpinBox {
    Q_OBJECT

public:
    ValueWriterInt(vector<int*> const& value): myValue(value) { 
        QObject::connect(this, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));
    }
    ~ValueWriterInt() {}

private slots:
    void    valueChanged(int new_value) {
        for (auto it = myValue.begin(); it != myValue.end(); ++it)
            **it = new_value;
    }

private:
    vector<int*>        myValue;
};
4

3 に答える 3

1

ウィジェットをそれ自体に接続することについて、特に奇妙なことは何もありません。データの更新を検出して応答する単一の方法を持つことは、デバッグ時にチェックする障害点が少なくなるため、実際には良いことのように思えます。あなたの特定のケースでは、望ましくない動作を引き起こしていますが、一般的には良い解決策です。

ここで、再帰接続は本質的に非エレガントではないという意見を表明したので、valueChanged構築後の呼び出しを防ぐための「エレガント」とは言えない解決策を提案します。オブジェクトが構築されたばかりかどうかを判断するフラグを設定し、早期に返して、構築直後にコードが実行されるのを防ぐことができます。あなたの例では:

class ValueWriterInt: public QSpinBox {
Q_OBJECT

public:
    ValueWriterInt(vector<int*> const& value): myValue(value), myAfterInit(true) { 
        QObject::connect(this, SIGNAL(valueChanged(int)), this, SLOT(valueChanged(int)));
    }
    ~ValueWriterInt() {}

private slots:
    void        valueChanged(int new_value) {
        if (myAfterInit) {
            myAfterInit = false;
            return;
        }
        for (auto it = myValue.begin(); it != myValue.end(); ++it)
                **it = new_value;
    }

private:
    vector<int*>                myValue;
    boolean                     myAfterInit;
};

それはそれほど悪い解決策ではありません。少なくとも、より洗練された方法が見つかるまで (およびその場合)、目的の動作が得られます。

于 2009-05-04T15:30:23.173 に答える
0

それで、あなたはここで何を達成しようとしていますか?はい、valueChanged は仮想ではありません。オブジェクトは、反応したい信号に自分のスロットを直接接続する必要があります。

于 2009-05-04T06:53:45.583 に答える
0

SIGNAL-SLOT 接続を使用する以外に方法はありません。ただし、スロットの名前を変更するので、信号と同じ名前にはなりません。

まだ接続が完了していない場合でも、スロットがどのように呼び出されるかは興味深いものです。スロットの名前を変更すると、その問題が解決すると思われます。

于 2009-05-04T08:48:05.170 に答える