Vorrei realizzare una finestra in cui, al variare ad esempio dell'elemento selezionato di una ComboBox,
cambia il widget visualizzato. Il widget visualizzato, fa parte di una gerarchia di oggetti derivati da una classe base.
Forse con qualche riga di codice diventa piu' facile intendersi.
codice:class Base: public QWidget { //questa e' la classe base coi suoi metodi enum Type: unsigned int { _Derived1,//0 _Derived2,//1 _TypeNumber//2 } } class Derived1: public Base { //primo tipo di widget } class Derived2: public Base { //secondo tipo di widget } class WidgetContainer: public QWidget //e' il widget che contiene la combobox e il widget 'variabile a runtime' da visualizzare { Q_OBJECT public: WidgetContainer(QWidget* parent = 0): QWidget(parent), mLayout(new QVBoxLayout(this)), mComboBox(new QComboBox(this)), mVariableWidget(new Derived1()) { mLayout->addWidget(mComboBox); mLayout->addWidget(mVariableWidget); //cambio l'indice della combobox, cambia il widget wisualizzato connect(mComboBox,SIGNAL(indexChanged(int)),this,changeWidget(int)); } private slots: void changeWidget(const int& index) { //pensavo di fare in questo modo: // prima tolgo il widget dal layout mLayout->removeWidget(mVariableWidget); // poi lo cancello delete mVariableWidget; // poi creo il nuovo widget, ad esempio mediante il metodo static di una classe Factory, e durante la creazione dico che il parent del nuovo VariableWidget e' this mVariableWidget = VariableWidgetFactory::make(index); //aggiungo il nuovo widget appena creato al layout mLayout->addWidget(mVariableWidget); //vedi testo sotto per alcuni commenti } private: QVBoxLayout* mLayout; QComboBox* mCombobox; Base* mVariableWidget; }
Il dubbio e': se chi usa il programma, seleziona la combobox e poi con la rotella del mouse fa cambiare l'indice 'a raffica', devo altrettanto a raffica distruggere e creare oggetti e tornare a visualizzarli, cosa che non mi sembra ottimale.
Un'alternativa che mi veniva in mente e' la seguente:
io so a priori quanti sono i possibili widget da visualizzare, e cioe' tanti quanti il numero di classi derivate da Base: nell'esempio sopra ad esempio 2.
Nella classe ContainerWidget, al posto di Base* mVariableWidget, potre quindi mettere
e aggiungere una variable che tiene l'indice del VariableWidget attualmente visualizzatocodice:Base* mVariableWidget[Base::_TypeNumber];
Nel costruttore quindi, potrei fare:codice:unsigned int mIndex;
poicodice:mVariableWidget[Base::_Derived1](new Derived1()), mVariableWidget[Base::_Derived2](nullptr)
e visualizzare coerentemente la combobox sull'indice Base::_Derived1 e il widget associato.codice:mLayout->addWidget(mVariableWidget[Base::_Derived1]); mIndex = Base::_Derived1;
Il metodo changeWidget potrebbe quindi diventare
creando i widget solo se viene richiesto, una sola volta, avendoli a disposizione senza ricrearli se devono essere rivisualizzati, e distruggendoli, sempre una sola volta, solo alla fine.codice:void changeWidget(const int& index) { mLayout->removeWidget(mVariableWidget[mIndex]); mVariableWidget[mIndex]->setVisible(false);//oppure uso ->hide(), fa qualche differenza? if(!mVariableWidget[index]) { //creo il nuov widget, e lo setto con parent this } mLayout->addWidget(mVariableWidget[index]);//in alternativa posso usare insertWidget, con l'indice relativo, se dopo il variable widget ce ne sono altri if(!mVariableWidget[index]->isVisible()) { mVariableWidget[index]->setVisible(true); } mIndex = index; }
Ci sono strade alternative?
Grazie

Rispondi quotando