PDA

View Full Version : dynamically building qdialog at runtime



Cremers
23rd October 2012, 13:40
Hello,
I want my QDialog class to react to the resizeevent (portrait/landscape for andriod).
But QWidget::setLayout for the dialog only works correctly when called from the constructor it seems.
So how is this done?

This does not work correctly, it shows widget2 on top of widget1:


Dialog::Dialog()
{
createstuff();
}

Dialog::createstuff()
{
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(widget1);
layout->addWidget(widget2);
..etc
setLayout(layout);
}


createstuff is going to have a parameter 'bool landscape' and will be called from resizeEvent() and I hope I will be able to use either a QVBoxLayout or a QHBoxLayout according to the event.
This is what I came up with, so if there are better ways please let me know..

wysota
23rd October 2012, 15:23
This does not work correctly, it shows widget2 on top of widget1:
What did you expect it to show?

Cremers
23rd October 2012, 15:36
When I call setLayout() from the constructor those 2 widgets (which are in itself QFormLayout's with some labels etc) are stacked vertically.
So that's what I was expecting, but it seems it only works when setLayout() is called from constructor.
This defeats the purpose of dynamically changing the layout at runtime.
Off course I may have the wrong approach totally.

wysota
23rd October 2012, 16:11
You mean that one is literally on the other (meaning parts of them occupy the same space)? Can you provide a code snippet that demonstrates the faulty behaviour? Also do you get any warnings in the console regarding the layout?

Cremers
23rd October 2012, 17:51
Screenshot http://jcremers.com/screenshot.png
You can see the 'layout 1' text behind the 'layout 2' text.
No warnings in console.
This is based on an example at http://qt-project.org/doc/qt-4.8/layouts-basiclayouts.html



Edit::Edit()
{
box1 = new QGroupBox(tr("layout1"));
box2 = new QGroupBox(tr("layout2"));
buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
}
//----------------------------------
void Edit::makeform(bool landscape)
{
QFormLayout *layout1 = new QFormLayout;
layout1->addRow(new QLabel(tr("Line 1:")), new QLineEdit);
layout1->addRow(new QLabel(tr("Line 2, long text:")), new QComboBox);
layout1->addRow(new QLabel(tr("Line 3:")), new QSpinBox);
box1->setLayout(layout1);
QFormLayout *layout2 = new QFormLayout;
layout2->addRow(new QLabel(tr("Line 1:")), new QLineEdit);
layout2->addRow(new QLabel(tr("Line 2, long text:")), new QComboBox);
layout2->addRow(new QLabel(tr("Line 3:")), new QSpinBox);
box2->setLayout(layout2);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(box1);
layout->addWidget(box2);
layout->addWidget(buttons);
setLayout(layout);
setWindowTitle(landscape ? "landscape" : "portrait");
}
//----------------------------------------------------------
void Edit::resizeEvent(QResizeEvent *event)
{
int w = event->size().width(), h = event->size().height();
QWidget::resizeEvent(event);
makeform(w > h);
}


I'll probably have done something stupid, yes?

wysota
23rd October 2012, 19:42
Yes, you created a new set of widgets instead of reusing those you already had. Since you removed the original layout but didn't remove the widgets in it, the widgets stayed where they were and new ones were put in the newly created layout.

Cremers
23rd October 2012, 20:41
LOL

I already was wondering about those 'new QLabel' etc.

Thanks.

Added after 34 minutes:

I still haven't got it right. I have created the widgets in the constructor in stead of on the stack.
When I set the layout of box2 to a simple widget, it works, but if I set it to layout2, the program crashes badly.



//----------------------------------
void Edit::makeform(bool landscape)
{
layout1->addRow(labelname, editname);
layout1->addRow(labeldate, editdate);
layout1->addRow(labeltime, edittime);
box1->setLayout(layout1);
layout2->addRow(labeldst, editdst);
box2->setLayout(layout2);
vlayout->addWidget(box1);
vlayout->addWidget(box2);
vlayout->addWidget(buttons);
setLayout(vlayout);
setWindowTitle(landscape ? "landscape" : "portrait");
}

Cremers
26th October 2012, 10:48
For what you are trying to do you should look at http://doc.qt.digia.com/latest/layouts-dynamiclayouts.html
Thanks.