PDA

View Full Version : Scrollbars for QStackedLayout



JohannesMunk
6th December 2009, 16:50
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:



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

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 = 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)),wdgsta ck,SLOT(setCurrentIndex(int)));
}
public slots:
void AddWidget(QString caption,QWidget* wdg)
{
wdgstack->addWidget(wdg);
list->addItem(caption);
}
private:
QListWidget* list;
CStackedWidget* wdgstack;
QScrollArea* sa;
};
A small example:



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();
}
Thx in advance for any recommendations!

Johannes