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
codice:
Base* mVariableWidget[Base::_TypeNumber];
e aggiungere una variable che tiene l'indice del VariableWidget attualmente visualizzato
codice:
unsigned int mIndex;
Nel costruttore quindi, potrei fare:
codice:
mVariableWidget[Base::_Derived1](new Derived1()),
mVariableWidget[Base::_Derived2](nullptr)
poi
codice:
mLayout->addWidget(mVariableWidget[Base::_Derived1]);
mIndex = Base::_Derived1;
e visualizzare coerentemente la combobox sull'indice Base::_Derived1 e il widget associato.
Il metodo changeWidget potrebbe quindi diventare
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;
}
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.
Ci sono strade alternative?
Grazie