Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different alignment of widgets in QGridLayout

The following code (Qt 5, same behaviour with Qt 4.8) uses a QGridLayout to add widgets above and to the left of a QScrollArea (to serve as a kind of header later):

#include <QApplication>
#include <QMainWindow>
#include <QGridLayout>
#include <QScrollArea>

class ColoredWidget : public QWidget {
public:
    ColoredWidget(const  QColor& color, QWidget* parent) : QWidget(parent) {
        QPalette pal;
        QBrush brush(color);
        brush.setStyle(Qt::SolidPattern);
        pal.setBrush(QPalette::Active, QPalette::Window, brush);
        setPalette(pal);
        setAutoFillBackground(true);
    }
};

class MainWindow : public QMainWindow {
public:
    MainWindow(QWidget* parent) : QMainWindow(parent) {
        resize(300, 400);

        QWidget* centralwidget = new ColoredWidget(QColor(0xff, 0xf0, 0xb5), this);

        QGridLayout* layout = new QGridLayout();
        centralwidget->setLayout(layout);
        setCentralWidget(centralwidget);

        // create widget with fixed height of 20 px and maximum width of 200
        QWidget* topHeader = new ColoredWidget(Qt::green, centralwidget);
        topHeader->setMaximumWidth(200);
        topHeader->setFixedHeight(20);

        // create widget with fixed width of 20 px and maximum height of 200
        QWidget* leftHeader = new ColoredWidget(Qt::blue, centralwidget);
        leftHeader->setFixedWidth(20);
        leftHeader->setMaximumHeight(200);

        // create scroll area as main widget
        QWidget* view = new QScrollArea();

        layout->addWidget(topHeader,  0, 1);
        layout->addWidget(leftHeader, 1, 0);
        // layout->addWidget(leftHeader, 1, 0, Qt::AlignTop); // widget not displayed at all!
        layout->addWidget(view, 1, 1);
    }
};


int main(int argc, char ** argv) {
    QApplication app( argc, argv );
    MainWindow win(0);
    win.show();
    return app.exec();
}

The QGridLayout documentation says that "Columns and rows behave identically", thus I would expect that the two widgets are layouted the same way.

However, the left one is automatically vertically centered, while the top widget is aligned to the left within the cell (and not centered horizontally). I would like to have the left widget also at a fixed position, means aligned to the top:

Strange Layout

  • Which property causes this different behaviour between the two widgets, one beeing centered, the other being at a fixed position?
  • How can I influence the alignment (I can probably add a flexible spacer to fix it, but ideally I would like to avoid that)? I tried with Qt::AlignTop, but that made the blue widget disappear.
like image 550
Andreas Fester Avatar asked Sep 13 '25 23:09

Andreas Fester


1 Answers

Setting the alignment either with:

layout->setAlignment(leftHeader, Qt::AlignHCenter | Qt::AlignTop);

or with:

layout->addWidget(leftHeader, 1, 0, Qt::AlignTop);

is intuitive and seems to be the right way. If it is setup completely it is also working as expected.

But why does the Widget vanish then?
Long story short: because leftHeader has a size of 0.

In my pretty similar situation I've setfixedHeight() and the widget reappeared, this should also work by setting a value for minimalHeight() for example.

Long Story - Details
I've put myself in position of gridLayout and tried to determine the size of leftHeader:

  1. Outside of the layout leftHeader got a fixed width of 20 - ok, but no given height.
    With the defaults of QWidget this leads to a default-height of 0.
  2. Documentation of void QGridLayout::addWidget() and void QGridLayout::addLayout() states:

...
The alignment is specified by alignment. The default alignment is 0, which means that the widget fills the entire cell.
...

source

Hence for default alignment of 0 the height of leftHeader is obviously set as height of its row.
But in case a different Qt::Alignment is used, as in the question (Qt::AlignTop ), it is not that simple.

From my point of view the layout is unable to determine the correct height without further settings from the designer.

Having a quick look at the implementation of void QGridLayout::addWidget(), we can detect that a QLayoutItem(as part of QGridBox) is created inside the QGridLayout for each added widget resp. Layout. So it seems that the QGridLayout relies on default layout mechanisms of Qt based on the settings from the added widget/Layout (like minSize, maxSize, BaseSize, Size Increment, etc ).

In combination with 1.) this implies a height of 0 for leftHeader and therefore nothing to draw resp. it seems that the widget has vanished.

like image 63
Marcus Helbig Avatar answered Sep 16 '25 13:09

Marcus Helbig