Em qt, como faço para implementar um widget que permaneça consistente com variáveis no código
Pergunta
Aqui está um exemplo de SpinBox que grava suas alterações nas variáveis subjacentes.O principal problema que estou tendo é que valueChanged é chamado quando o widget é construído.Existe uma maneira mais elegante de fazer isso?Acho estranho ter conectado um widget a ele mesmo, mas valueChanged não é virtual.
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;
};
Solução
Não vejo nada de particularmente estranho em conectar um widget a si mesmo.Ter um único método para detectar e responder às atualizações de dados realmente parece uma coisa boa porque você tem menos pontos de falha para verificar durante a depuração.No seu caso específico, está causando algum comportamento indesejado, mas em geral é uma boa solução.
Agora, tendo expressado a opinião de que uma conexão reflexiva não é inerentemente deselegante, vou sugerir uma solução nada "elegante" para evitar a chamada de valueChanged
após a construção.Você pode ter um sinalizador para determinar se o objeto acabou de ser construído e retornar antecipadamente para evitar que o código seja executado imediatamente após a construção.No seu exemplo:
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;
};
Essa não é uma solução tão ruim.Pelo menos lhe dará o comportamento desejado até (e se) você encontrar um método mais elegante.
Outras dicas
Então, o que você está tentando realizar aqui?Sim, valueChanged não é virtual - por que deveria ser, seus objetos devem se conectar diretamente seus próprios slots para quaisquer sinais aos quais eles queiram reagir, não?
Não vejo outra alternativa senão usar conexões SIGNAL-SLOT.Porém, eu mudaria o nome do slot, para que não tenha o mesmo nome do sinal.
É intrigante como o slot é chamado, mesmo que ainda não tenha sido feita nenhuma conexão.Suspeito que mudar o nome do slot resolverá esse problema.