PDA

View Full Version : QFrame questions



zephod
13th August 2013, 02:48
I have a few questions about frames.
Here is a test program I have been experimenting with


class BuildGui : public QMainApplication
{
public:
BuildGui(QWidget* parent = 0);
private:
QWidget* makeWidget(QString text);

QVBoxLayout* layout;
};

BuildGui::BuildGui(QWidget* parent = 0) : QMainApplication(parent)
{
QWidget* w1 = makeWidget("Ex 1");
QWidget* w2 = makeWidget("Ex 2");

layout = new QVBoxLayout;
layout->addWidget(w1);
layout->addWidget(w2);

QWidget* cw = new QWidget;
cw->setLayout(layout);

QScrollArea* sa = new QScrollArea;
sa->setWidget(cw);

setCentralWidget(sa);
}

QWidget* BuildGui::makeWidget(QString text)
{
QLineEdit* le = new QLineEdit(text);
return le;
}

which works as expected - I see the 2 text boxes one above the other with "Ex 1" and "Ex 2" for the text.

Now I add this method:

QWidget* BuildGui::addFrame(QWidget w)
{
QFrame* f = new QFrame;
f->setFrameStyle(QFrame::Box);
w->setParent(f);
return f;
}

and modify the constructor:


QWidget* f1 = addFrame(sc1);
...
// layout->setWidget(w1);
layout->setWidget(f1);

now the "Ex 1" box does not show up. If I add

f1->setMinimumSize(50,50);
then it is visible.
So my question is
Can i make the frame automatically adjust to the size of the widget it is framing?

Thanks,
Steve

PS I know some widgets have a setFrame() method but I want this to work for framinh any widget.

ChrisW67
13th August 2013, 10:22
If you were correctly using a Qt layout inside the frame then the frame would drive the size of the contained widget within the constraints imposed on the layout and widget. Regardless of the original size of the QFrame once you add it to a larger layout its size will be controlled by that layout.

Qt does not, as a rule, operate in the content-drives-container-size direction because size constraints naturally flow down from the available desktop space, to the uppermost window and down to smaller and smaler widgets.

zephod
13th August 2013, 16:09
I'm finding this very confusing.
I set a main window size of 210x210 in the main program.

I create 3 LineEdits, add them to the vbox and they show up taking the minimum amount of space.

I add a frame around the first one and it disappears.

I set a size of 200x200 on the widget that the layout is set on, cw in my code example, now the frame shows up but it is a frame around the space not around the LineEdit.
The 2 LineEdits without a frame are at the bottom and take up the minimum space they can while the frame takes up the rest of the 200 vertical space.
You explained this saying that the frame is controlled by the layout it is placed in.

I really want the top 2 widgets to take up the minimum space and let the bottom one expand to fill the rest of the space so I added:
layout->setStretchFactor(sc3,1)

My understanding (if you can call it that) is that the stretch factor is turned off by default so turning it on for one widget will cause that widget to stretch to take up the maximum space but what this did is remove the 1st widget!?!

You said that "Qt does not, as a rule, operate in the content-drives-container-size direction". Does that imply that it is possible to make it work that way?

ChrisW67
13th August 2013, 23:30
A QLineEdit has a fixed vertical height, i.e. a single line of text, so trying to stretch it vertically does not make a lot of sense. If the widget were QTextEdits then the result would be different.


Does that imply that it is possible to make it work that way?
Yes, to some degree, but you have to use the layouts correctly. The content of the frame is controlled by a layout or not at all as in your code. In your code the frame owns the widget but there is no layout applied so the widget and frame are independently sized. This is likely why it "disappears".



QWidget *wrapWithFrame(QWidget *widget) {
if (!widget)
return widget;

QFrame *frame = new QFrame(widget->parentWidget());
frame->setFrameStyle(QFrame::Box);

QVBoxLayout *layout = new QVBoxLayout(frame);
layout->setContentsMargins(0, 0, 0, 0);
// layout->setSizeConstraint(QLayout::SetFixedSize); // << you might like to read and experiment
layout->addWidget(widget);
frame->setLayout(layout);
return frame;
}

zephod
16th August 2013, 03:07
Thanks, that's what I needed.

I was thinking that a layout controlled how multiple widgets were layed out in relation to each other and hadn't considered that a single widget would need a layout.