Hello!
I have worked out a solution that works for me, but I would like to know, if I missed a more elegant solution.
I needed a widget, that shows a list of several possible user interfaces, that fit into a defined space. Therefore I put a StackedLayout into a Scrollarea.
First: A StackedLayout that has its minimumSize set depending only on the currentwidget and not all its child-widgets:
{ Q_OBJECT
public:
{
if (cw
) return cw
->sizeHint
();
else return QSize(0,
0);
}
QSize minimumSize
() const {
if (cw
) return cw
->minimumSize
();
else return QSize(0,
0);
}
};
class CStackedLayout : public QStackedLayout
{ Q_OBJECT
public:
explicit CStackedLayout(QWidget *parent = 0) : QStackedLayout(parent) {}
QSize sizeHint() const
{
QWidget* cw = currentWidget();
if (cw) return cw->sizeHint(); else return QSize(0,0);
}
QSize minimumSize() const
{
QWidget* cw = currentWidget();
if (cw) return cw->minimumSize(); else return QSize(0,0);
}
};
To copy to clipboard, switch view to plain text mode
Based on that StackLayout I build a StackedWidget, that updates its minimumSize, if appropriate:
class CStackedWidget
: public QFrame{ Q_OBJECT
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentChanged)
Q_PROPERTY(int count READ count)
public:
{
layout = new CStackedLayout(this);
connect(layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int)));
connect(layout, SIGNAL(currentChanged(int)), this, SLOT(updateConstraints()));
connect(layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int)));
}
int addWidget
(QWidget *w
) {return layout
->addWidget
(w
);
} int insertWidget
(int index,
QWidget *w
) {return layout
->insertWidget
(index, w
);
} void removeWidget
(QWidget *w
) {layout
->removeWidget
(w
);
}
QWidget *currentWidget
() const {return layout
->currentWidget
();
} int currentIndex() const {return layout->currentIndex();}
int indexOf
(QWidget *w
) const {return layout
->indexOf
(w
);
} QWidget *widget
(int index
) const {return layout
->widget
(index
);
} int count() const {return layout->count();}
public slots:
void setCurrentIndex(int index) {layout->setCurrentIndex(index);}
void setCurrentWidget
(QWidget *w
) {layout
->setCurrentWidget
(w
);
}
void updateConstraints() {setMinimumSize(layout->minimumSize().width(),layout->minimumSize().height());resize(size());}
signals:
void currentChanged(int);
void widgetRemoved(int index);
private:
CStackedLayout* layout;
};
class CStackedWidget : public QFrame
{ Q_OBJECT
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentChanged)
Q_PROPERTY(int count READ count)
public:
explicit CStackedWidget(QWidget *parent=0) : QFrame(parent)
{
layout = new CStackedLayout(this);
connect(layout, SIGNAL(widgetRemoved(int)), this, SIGNAL(widgetRemoved(int)));
connect(layout, SIGNAL(currentChanged(int)), this, SLOT(updateConstraints()));
connect(layout, SIGNAL(currentChanged(int)), this, SIGNAL(currentChanged(int)));
}
int addWidget(QWidget *w) {return layout->addWidget(w);}
int insertWidget(int index, QWidget *w) {return layout->insertWidget(index, w);}
void removeWidget(QWidget *w) {layout->removeWidget(w);}
QWidget *currentWidget() const {return layout->currentWidget();}
int currentIndex() const {return layout->currentIndex();}
int indexOf(QWidget *w) const {return layout->indexOf(w);}
QWidget *widget(int index) const {return layout->widget(index);}
int count() const {return layout->count();}
public slots:
void setCurrentIndex(int index) {layout->setCurrentIndex(index);}
void setCurrentWidget(QWidget *w) {layout->setCurrentWidget(w);}
void updateConstraints() {setMinimumSize(layout->minimumSize().width(),layout->minimumSize().height());resize(size());}
signals:
void currentChanged(int);
void widgetRemoved(int index);
private:
CStackedLayout* layout;
};
To copy to clipboard, switch view to plain text mode
And a multiwidget selector class, which shows a ListWidget from which you can choose the current widget of the stack.
class CMultiWidget
: public QWidget{ Q_OBJECT
public:
CMultiWidget()
{
list->setMinimumWidth(30);
list->setMaximumWidth(100);
wdgstack = new CStackedWidget();
wdgstack->setContentsMargins(0,0,0,0);
sa->setWidgetResizable(true);
sa->setWidget(wdgstack);
sa->setContentsMargins(0,0,0,0);
sa
->setFrameStyle
(QFrame::NoFrame);
layout->addWidget(list,0);
layout->addWidget(sa,1);
setLayout(layout);
connect(list,SIGNAL(currentRowChanged(int)),wdgstack,SLOT(setCurrentIndex(int)));
}
public slots:
{
wdgstack->addWidget(wdg);
list->addItem(caption);
}
private:
CStackedWidget* wdgstack;
};
class CMultiWidget : public QWidget
{ Q_OBJECT
public:
CMultiWidget()
{
list = new QListWidget();
list->setMinimumWidth(30);
list->setMaximumWidth(100);
wdgstack = new CStackedWidget();
wdgstack->setContentsMargins(0,0,0,0);
sa = new QScrollArea();
sa->setWidgetResizable(true);
sa->setWidget(wdgstack);
sa->setContentsMargins(0,0,0,0);
sa->setFrameStyle(QFrame::NoFrame);
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget(list,0);
layout->addWidget(sa,1);
setLayout(layout);
connect(list,SIGNAL(currentRowChanged(int)),wdgstack,SLOT(setCurrentIndex(int)));
}
public slots:
void AddWidget(QString caption,QWidget* wdg)
{
wdgstack->addWidget(wdg);
list->addItem(caption);
}
private:
QListWidget* list;
CStackedWidget* wdgstack;
QScrollArea* sa;
};
To copy to clipboard, switch view to plain text mode
A small example:
class CContentWidget
: public QWidget{ Q_OBJECT
public:
CContentWidget(int listcount,int w,int h)
{
setMinimumSize(w,h);
for (int i = 0;i < listcount;++i)
{
}
setLayout(hl);
}
private:
};
int main(int argc, char *argv[])
{
CMultiWidget w;
w.resize(600,300);
w.AddWidget("A",new CContentWidget(2,250,150));
w.AddWidget("B",new CContentWidget(3,250,500));
w.show();
return a.exec();
}
class CContentWidget : public QWidget
{ Q_OBJECT
public:
CContentWidget(int listcount,int w,int h)
{
setMinimumSize(w,h);
QHBoxLayout* hl = new QHBoxLayout();
for (int i = 0;i < listcount;++i)
{
hl->addWidget(new QListWidget());
}
setLayout(hl);
}
private:
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CMultiWidget w;
w.resize(600,300);
w.AddWidget("A",new CContentWidget(2,250,150));
w.AddWidget("B",new CContentWidget(3,250,500));
w.show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
Thx in advance for any recommendations!
Johannes
Bookmarks