QGridLayout中小部件的不同对齐方式

4
以下代码(Qt 5,Qt 4.8 行为相同)使用 QGridLayoutQScrollArea 上方和左侧添加小部件(以后可用作标题)。请保留 HTML 标记。
#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();
}
QGridLayout的文档中提到“列和行的行为相同”,因此我期望这两个小部件的布局方式是相同的。然而,左边的小部件自动垂直居中,而顶部的小部件在单元格内“靠左对齐”(并且水平上不居中)。我希望左侧的小部件也处于固定位置,即与顶部对齐:
两个小部件之间有什么属性导致它们的行为不同,一个被居中,另一个处于固定位置?
我该如何影响对齐方式(可能可以添加灵活的间隔器来修复,但理想情况下我希望避免这种方法)?我尝试使用Qt::AlignTop,但这使蓝色的小部件消失了。
3个回答

5
尽管这个问题已经很老了,但我会为所有后来者(比如我)添加我的答案。
使用以下两种方法之一设置对齐方式:
layout->setAlignment(leftHeader, Qt::AlignHCenter | Qt::AlignTop);

layout->addWidget(leftHeader, 1, 0, Qt::AlignTop);
这是直观的,并且似乎是正确的方法。如果完全设置好了,它也可以按预期工作。 但是为什么窗口小部件会消失呢?
长话短说:因为leftHeader的大小为0。
在我的类似情况下,我使用了setfixedHeight(),然后窗口小部件重新出现了,这也可以通过例如为minimalHeight()设置一个值来实现。 长故事 - 详细信息
我把自己放在网格布局的位置上,试图确定leftHeader的大小:
  1. 在布局之外,leftHeader的固定宽度为20 - 好的,但没有给定的高度。
    根据QWidget的默认值,这导致默认高度为0。
  2. void QGridLayout::addWidget()void QGridLayout::addLayout()的文档说明:

...
对齐方式由alignment指定。默认对齐方式为0,这意味着窗口小部件填充整个单元格。
...

来源

因此,默认对齐方式为0时,leftHeader的高度显然设置为其行的高度。
但是,如果使用不同的Qt::Alignment,如问题中所述(Qt::AlignTop),情况就不那么简单了。
从我的角度来看,布局无法在没有设计师进一步设置的情况下确定正确的高度。
快速查看void QGridLayout::addWidget()的实现,我们可以发现每个添加的窗口小部件或布局在QGridLayout内创建一个QLayoutItem(作为QGridBox的一部分)。 因此,QGridLayout依赖于基于添加的窗口小部件/布局的设置(如minSizemaxSizeBaseSizeSize Increment等)的Qt的默认布局机制。
结合1.),这意味着leftHeader的高度为0,因此没有任何东西可绘制,或者看起来窗口小部件已经消失了。

1
非常感谢您提供这么详细的答案 - 即使过了几年,它仍然非常有用 :-) - Andreas Fester

1
尽管不是最简单的解决方案,但您可以通过在绿色小部件的单元格中添加一个QHBoxLayout,并在蓝色小部件的单元格中添加一个QVBoxLayout来修复对齐方式。将绿色小部件添加到QHBoxLayout中,将蓝色小部件添加到QVBoxLayout中。然后在QHBoxLayoutQVBoxLayout上应用addStretch(n)。也许这就是您已经提到过的,那么我们在这个问题上的知识水平就相同了。我相信这是我解决这些问题的方法,我没有花更多的时间在上面。

谢谢你的回答 - 这确实是我大致想到的“解决方法” :) 无论如何,你的解决方案有效,但我仍然很好奇为什么会有这种行为差异... - Andreas Fester

0

试试这个:

setAlignment(Qt::AlignHCenter | Qt::AlignTop );

你的意思是使用 layout->setAlignment(leftHeader, Qt::AlignHCenter | Qt::AlignTop); 来设置蓝色小部件的对齐方式吗?这会使蓝色小部件不可见... - Andreas Fester

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接