En qt, ¿cómo implemento un widget que se mantenga consistente con las variables en el código?

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

  •  03-07-2019
  •  | 
  •  

Pregunta

Aquí hay una muestra de un SpinBox que escribe sus cambios en las variables subyacentes. El principal problema que tengo es que valueChanged se llama cuando se construye el widget. ¿Hay una manera más elegante de hacer esto? Creo que es extraño que haya conectado un widget a sí mismo, pero valueChanged no es 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;
};
¿Fue útil?

Solución

No veo nada particularmente extraño acerca de conectar un widget a sí mismo. Tener un solo método para detectar y responder a las actualizaciones de datos en realidad suena como algo bueno porque tiene menos puntos de falla para verificar cuando está depurando. En su caso específico, está causando un comportamiento no deseado, pero en general es una buena solución.

Ahora, habiendo expresado la opinión de que una conexión reflexiva no es intrínsecamente poco elegante, voy a sugerir un menos que " elegante " solución para evitar la llamada de valueChanged después de la construcción. Puede tener una marca para determinar si el objeto se acaba de construir y regresar antes para evitar que el código se ejecute inmediatamente después de la construcción. En tu ejemplo:

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;
};

Eso no es una solución tan mala. Al menos le dará el comportamiento deseado hasta (y si) puede encontrar un método más elegante.

Otros consejos

Entonces, ¿qué estás tratando de lograr aquí? Sí, valueChanged no es virtual: ¿por qué debería serlo, sus objetos deberían conectar directamente sus propias ranuras a cualquier señal a la que quieran reaccionar, no?

No veo otra alternativa que utilizar las conexiones SIGNAL-SLOT. Sin embargo, cambiaría el nombre de la ranura, para que no tenga el mismo nombre que la señal.

Es intrigante cómo se llama a la ranura incluso si todavía no se ha realizado la conexión. Sospecho que cambiar el nombre de la ranura resolverá ese problema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top