Dans qt, comment implémenter un widget qui reste cohérent avec les variables du code

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

  •  03-07-2019
  •  | 
  •  

Question

Voici un exemple de SpinBox qui écrit ses modifications dans les variables sous-jacentes. Le problème principal que je rencontre est valueChanged est appelé lors de la construction du widget. Y a-t-il une manière plus élégante de faire ceci? Je pense que c'est étrange que j'ai connecté un widget à lui-même, mais valueChanged n'est pas virtuel.

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;
};
Était-ce utile?

La solution

Je ne vois rien de particulièrement bizarre à propos de la connexion d'un widget à lui-même. Avoir une seule méthode de détection et de réponse aux mises à jour des données semble être une bonne chose, car vous avez moins de points d’échec à vérifier lorsque vous effectuez un débogage. Dans votre cas particulier, cela provoque un comportement indésirable, mais en général c'est une bonne solution.

Maintenant, après avoir exprimé l’opinion qu’une connexion réflexive n’est pas intrinsèquement inélégante, je vais suggérer une solution moins que élégante. solution pour empêcher l’appel de valueChanged après la construction. Vous pouvez avoir un indicateur pour déterminer si l'objet vient d'être construit et le renvoyer plus tôt pour empêcher le code d'être exécuté immédiatement après la construction. Dans votre exemple:

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

Ce n’est pas une trop mauvaise solution. Cela vous donnera au moins le comportement souhaité jusqu'à ce que (et si) vous puissiez trouver une méthode plus élégante.

Autres conseils

Alors, qu'essayez-vous d'accomplir ici? Oui, valueChanged n'est pas virtuel - pourquoi devrait-il en être ainsi, vos objets devraient connecter directement leurs propres emplacements aux signaux auxquels ils souhaitent réagir, non?

Je ne vois pas d'autre alternative que d'utiliser des connexions SIGNAL-SLOT. Cependant, je changerais le nom de la fente afin qu'elle n'ait pas le même nom que le signal.

La façon dont le logement est appelé intrigue, même si aucune connexion n’est encore établie. Je pense que changer le nom de la fente résoudra ce problème.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top