qtでは、コード内の変数と一貫性を保つウィジェットをどのように実装しますか
質問
変更を基になる変数に書き込む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;
};
解決
ウィジェットをそれ自体に接続することについて、特に奇妙なことは何もありません。デバッグ時にチェックする障害点が少ないため、データ更新を検出して応答する単一の方法があるのは実際には良いことのように思えます。あなたの特定の場合、それはいくつかの望ましくない動作を引き起こしていますが、一般的には素晴らしい解決策です。
今、反射的なつながりは本質的にエレガントではないという意見を表明したので、「エレガント」未満を提案します。構築後の 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;
};
それは解決策としてそれほど悪くはありません。少なくとも、よりエレガントな方法が見つかるまで(およびその場合)、目的の動作を提供します。
他のヒント
では、ここで何を達成しようとしていますか?はい、valueChangedは仮想ではありません-なぜそうすべきなのですか、オブジェクトは自分のスロットを、反応したい信号に直接接続する必要がありますか?
SIGNAL-SLOT接続を使用する以外の方法はありません。ただし、スロットの名前を変更するため、信号と同じ名前はありません。
まだ接続が行われていない場合でも、スロットがどのように呼び出されるかは興味深いです。スロットの名前を変更することでその問題が解決すると思われます。