In qt, come posso implementare un widget che rimane coerente con le variabili nel codice

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

  •  03-07-2019
  •  | 
  •  

Domanda

Ecco un esempio di uno SpinBox che scrive le sue modifiche nelle variabili sottostanti. Il problema principale che sto riscontrando è valueChanged viene chiamato quando viene creato il widget. C'è un modo più elegante per farlo? Penso che sia strano che abbia collegato un widget a se stesso, ma valueChanged non è virtuale.

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;
};
È stato utile?

Soluzione

Non vedo nulla di particolarmente strano nel collegare un widget a se stesso. Avere un solo metodo per rilevare e rispondere agli aggiornamenti dei dati suona davvero come una buona cosa perché hai meno punti di errore da controllare durante il debug. Nel tuo caso specifico, sta causando un comportamento indesiderato, ma in generale è un'ottima soluzione.

Ora, dopo aver espresso l'opinione che una connessione riflessiva non è intrinsecamente inelegante, suggerirò un valore inferiore a "elegante". soluzione per impedire la chiamata di valueChanged dopo la costruzione. Puoi avere un flag per determinare se l'oggetto è stato appena costruito e tornare presto per impedire che il codice venga eseguito immediatamente dopo la costruzione. Nel tuo esempio:

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

Una soluzione non è poi così male. Almeno ti darà il tuo comportamento desiderato fino a quando (e se) riuscirai a trovare un metodo più elegante.

Altri suggerimenti

Quindi cosa stai cercando di realizzare qui? Sì, valueChanged non è virtuale - perché dovrebbe essere, i tuoi oggetti dovrebbero connettere direttamente i propri slot ai segnali a cui vogliono reagire, no?

Non vedo altra alternativa che usare le connessioni SIGNAL-SLOT. Tuttavia, cambierei il nome dello slot, quindi non ha lo stesso nome del segnale.

È interessante il modo in cui viene chiamato lo slot anche se non è stata ancora effettuata alcuna connessione. Sospetto che la modifica del nome dello slot risolverà il problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top