Em qt, como faço para implementar um widget que permaneça consistente com variáveis ​​no código

StackOverflow https://stackoverflow.com/questions/818981

  •  03-07-2019
  •  | 
  •  

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;
};
Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top