PDA

View Full Version : Layout



buster
10th January 2020, 12:44
I am trying to create a layout on top of a widget derived from QWidget:

myWidget::myWidget(QWidget *parent, const char *name )
{
setFixedSize(300, 150); // Just for now

m_plotpanel = new PlotPanel(this); // PlotPanel is scubclassed from QWidget, not MainWindow
m_controllpanel = new PlotPanel(this); // for now
m_plotpanel->setStyleSheet("background-color: red"); // to see that
m_controllpanel->setStyleSheet("background-color: black"); // they are both there

horLayout = new QHBoxLayout;
horLayout->addWidget(m_plotpanel);
horLayout->addWidget(m_controllpanel);
m_plotpanel->show();
m_controllpanel->show();

13311

Both widgets are shown, with the right colours, but they are detached from myWidget. How can I attach them to myWidget? Do I have to use QDockWidget?

Lesiok
10th January 2020, 13:43
Add this line (QWidget::setLayout):
setLayout(horLayout);

buster
10th January 2020, 14:25
Add this line (QWidget::setLayout):
setLayout(horLayout);
I have tried that, but them I the widgets do not show at all.

d_stranz
10th January 2020, 17:52
Remove the two show() calls for the child widgets. They will be "shown" when your myWidget instance is shown. And add the "setLayout()" call instead.

If myWidget is derived from QWidget and you intend for it to be the central widget for a QMainWindow, then you need to call setCentralWidget() with the pointer in your main window constructor. If it is meant to be a standalone, top-level widget (i.e. floating), then at some point in your code you also need to call show() on the myWidget instance.

buster
10th January 2020, 18:43
Remove the two show() calls for the child widgets. They will be "shown" when your myWidget instance is shown. And add the "setLayout()" call instead.

If myWidget is derived from QWidget and you intend for it to be the central widget for a QMainWindow, then you need to call setCentralWidget() with the pointer in your main window constructor. If it is meant to be a standalone, top-level widget (i.e. floating), then at some point in your code you also need to call show() on the myWidget instance.

I have got a QStackedWidget in my MainWindow and I call setCentralWidget there:


setCentralWidget(m_StackedWidget);

and that works perfectly, in the sense that I can change between the two stacked widgets (using slots). myWidget is supposed to "sit on top of" both of these stacked widgets, so maybe there is some interaction here that I have not understood? The widgests in the layout still do not show; without


setLayout(horLayout)
the two widgets in my layout are visible, but free-floating. With


setLayout(horLayout)

they remain hidden, and I see the top stacked widget (they have all got different colours).

d_stranz
11th January 2020, 01:01
So, how are you creating your instance of myWidget? As a child of your QMainWindow or of the QStackedWidget? In that case, it is probably being shown but is hidden behind the main window or stacked widget.

If you want your myWindow instance to be free-floating, then you need to create it as a top-level widget (i.e. with a NULL parent) and call its show() method to make it visible. It will be free-floating and completely independent of your main window, so it is possible that when it is shown, it will actually be behind the main window and you will have to move the main window to be able to see it. That could be what is happening now.

The reason your two widgets are being shown independently with your current code is that even though you are adding them to a layout, you aren't putting that layout into any widget. So when you call show() on those sub-widgets, they essentially get re-parented (with NULL parents) as top-level widgets, ignoring the layout.

If myWidget is free-floating, it can be anywhere on the screen and won't be confined to the area of the main window.

buster
11th January 2020, 11:29
So, how are you creating your instance of myWidget? As a child of your QMainWindow or of the QStackedWidget? In that case, it is probably being shown but is hidden behind the main window or stacked widget.

If you want your myWindow instance to be free-floating, then you need to create it as a top-level widget (i.e. with a NULL parent) and call its show() method to make it visible. It will be free-floating and completely independent of your main window, so it is possible that when it is shown, it will actually be behind the main window and you will have to move the main window to be able to see it. That could be what is happening now.

The reason your two widgets are being shown independently with your current code is that even though you are adding them to a layout, you aren't putting that layout into any widget. So when you call show() on those sub-widgets, they essentially get re-parented (with NULL parents) as top-level widgets, ignoring the layout.

If myWidget is free-floating, it can be anywhere on the screen and won't be confined to the area of the main window.

I finally got it working. The problem turned out to be that I had no widgets on m_plotpanel, so I think that the layout was OK, but its dimensions were probably zero (0x0). Declaring a QLabel in m_plotpanel, thus


QLabel *label = new QLabel(this);

made the red and black widgets show up as two small squares. Inserting some text increased the size accordingly. Adding layout to m_plotpanel also works as I wold expect from the documentation, so my problem is solved.

Although it doesn't really matter, I am a bit curious why empty labels have finite dimensions. Do they have some minimum size? Anyway, thanks for the help.

d_stranz
11th January 2020, 17:56
Although it doesn't really matter, I am a bit curious why empty labels have finite dimensions. Do they have some minimum size? Anyway, thanks for the help.

Glad you got it working. I didn't realize your two child widgets were empty. When I am mocking up a UI and want some placeholders that I will replace later with real widgets, I usually choose a QTreeView or QTableView since these have a finite size and will expand to fill the space they are placed into.

QLabel inherits from QFrame, which contains a frameWidth property. It defaults to 1, so there is a 1-pixel border all around it. Layouts also contain a margin, which separates the layout from its container as well as establishes padding between items in the layout. So there is almost always some empty space allocated to yield a finite size.