Tatarinho
Tatarinho

Reputation: 784

Qt remove empty space between widgets on QVBoxLayout

I have annoying problem. I created QVBoxLayout on which I added my widgets. This is sample from my constructor:

layout = new QVBoxLayout;
layout->setMargin(0);
layout->setContentsMargins(QMargins(0,0,0,0));
layout->setSpacing(0);

And then I have function to add widgets.

layout->addWidget(_wave);

_wave is my own widget. But you can add whatever you want, for example QButton.

What do I want achieve? Similar like this but without any spaces beetween widgets added to layout. Just only QButtons or other widget, sticked each other.

I added everywhere setMargins, setSpacing etc. Please help me with that, I don't really have an idea what should I do.

enter image description here

Sorry for colors, but I wanted to mentioned what I want to achieve. I have mainWindow on which I added QWidget. This widget have blue background. Then to the layout, Im addding some widgets, which are orange on this image. I just want to be sure, that this blue background between widget isnt visible. I want to have widget under widget, without any space.

Upvotes: 11

Views: 22851

Answers (5)

Jeremy
Jeremy

Reputation: 71

It seems like by default QT layouts do stretch their child widgets to fill the space of the layout. I found a way to achieve what I believe you are looking for. You can add a spacer to the layout with sizeType Expanding (default), and it will take up all the space in the layout and shrink the other widgets to their minimum size. You can do this in the visual designer of QT Creator or in code with something like this:

QVBoxLayout *layout = ui->verticalLayout_2;
layout->setContentsMargins(QMargins(0,0,0,0));
layout->setSpacing(0);
QSpacerItem *spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding);
layout->addSpacerItem(spacer);

for (int i=0; i<5; ++i)
{
    auto button = new QPushButton(ui->centralwidget);
    button->setText("Click me");
    layout->insertWidget(layout->count() - 1, button, 0, Qt::AlignmentFlag::AlignTop);
}

If done in code you'll probably want to insert the widget at count() - 1, so the spacer is the last item in the layout.

Edit: kiss-o-matic's answer does actually the exact same thing in 1 line. And yeah it would probably be better to add the spacer after all other items unless, like me, you're doing it for a scroll area where items will be added by user input. That's why I added spacer first then items later.

Upvotes: 2

Tay2510
Tay2510

Reputation: 5978

Spacing Never Zero?

As the Qt document says, some default GUI widget has extra frame around it.

Take QPushButton as an example:

In some GUI styles a default button is drawn with an extra frame around it, up to 3 pixels or more. Qt automatically keeps this space free around auto-default buttons, i.e. auto-default buttons may have a slightly larger size hint.

So the culprit is not the layout but the widget itself instead. "Invisible" margin of a default widget remains even if the spacing of the layout has been set to 0.

Solution

If you really need a "compact" layout, my suggestion is to resort to the stylesheet of the widget.


Examples

Here are examples to illustrate the idea:

Here, we have a vertical layout with both margin and spacing equal to 0, and the buttons with custom stylesheet:

 QPushButton {
     border: 2px solid #8f8f91;
     border-radius: 6px;
     background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
                                       stop: 0 #f6f7fa, stop: 1 #dadbde);
     min-width: 80px;
 }

// (further stylesheet for button click is needed)

Resetting stylesheet allows us to make the layout more compact:

enter image description here

Insert a default QPushButton to see the difference:

enter image description here

You can see there is space around the default QPushButton. That's the same for other kinds of widgets.

Upvotes: 2

BaldDude
BaldDude

Reputation: 1161

I know the question was posted a year ago, but if it can help some people save some time, I would be glad. I had the same problem and was able to solve it by setting:

  • QFrame.setFrameShape() to NoFrame
  • QFrame.setLineWidth() to 0.

The image below is the result of 2 QtextEdit put side by side in a Layout, using the described method.

enter image description here

http://doc.qt.io/qt-5/qframe.html#lineWidth-prop

Upvotes: 6

kmcguire
kmcguire

Reputation: 904

I could be wrong but there does not seem to be an obvious and non-hack of a way to do what you desire. However, according to the documentation you may find that just doing a manual layout will solve your problem. (http://doc.qt.io/qt-5/layout.html : Manual Layout)

It seems as if one could implement a Layout class that actually provides a very compact horizontal or vertical layout and I believe I had written one a few years ago using Python and Qt. With that in mind, you should be able to implement your own MyCompactLayout(horizontal=True) and use it.

Upvotes: 1

kiss-o-matic
kiss-o-matic

Reputation: 1181

Try this to achieve a "tight" look. Note that if you resize the parent widget, they will not move. Not sure if this is what you want or not, but...

// After all widgets are added to the layout
layout->insertStretch( -1, 1 );

The 2nd argument needs to be higher than any other stretch factor. Stretch factor is default zero, so if you don't set it, the above one-liner should work.

Upvotes: 4

Related Questions