【问题标题】:Set Vertical Alignment of QFormLayout QLabel设置 QFormLayout QLabel 的垂直对齐方式
【发布时间】:2016-01-06 23:27:25
【问题描述】:

我正在使用 PySide/PyQt,但这是一个通用的 Qt 问题。

有没有办法设置 QFormLayout 使标签垂直居中,而无需显式创建 QLabel 并将其垂直大小策略设置为先扩展?当第 2 列中的小部件高于我的标签时,我希望我的标签与小部件垂直居中,而不是与其顶部对齐...

这是一个演示该问题的示例脚本。我已将标签涂成红色以更好地展示它们的大小行为。

from PySide import QtCore, QtGui

app = QtGui.QApplication([])

widget = QtGui.QWidget()
widget.setStyleSheet("QLabel { background-color : red}")

layout = QtGui.QFormLayout()
layout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
layout.setLabelAlignment(QtCore.Qt.AlignCenter)

editor1 = QtGui.QLineEdit()
editor1.setFixedSize(300, 100)

editor2 = QtGui.QLineEdit()
editor2.setFixedSize(300, 100)

layout.addRow('Input', editor1)
layout.addRow('Longer Named Input', editor2)

widget.setLayout(layout)

widget.show()

app.exec_()

结果如下:

这是一个示例,通过显式创建 QLabel 并为它们提供扩展大小策略来演示所需的结果:

from PySide import QtCore, QtGui

app = QtGui.QApplication([])

widget = QtGui.QWidget()
widget.setStyleSheet("QLabel { background-color : red}")

layout = QtGui.QFormLayout()
layout.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow)
layout.setLabelAlignment(QtCore.Qt.AlignCenter)

editor1 = QtGui.QLineEdit()
editor1.setFixedSize(300, 100)

editor2 = QtGui.QLineEdit()
editor2.setFixedSize(300, 100)

label1 = QtGui.QLabel('Input')
expand = QtGui.QSizePolicy.Expanding
label1.setSizePolicy(expand, expand)

label2 = QtGui.QLabel('Longer Named Input')
label2.setSizePolicy(expand, expand)

layout.addRow(label1, editor1)
layout.addRow(label2, editor2)

widget.setLayout(layout)

widget.show()

app.exec_()

这就是结果......

我试过QFormLayout.setLabelAlignment() 似乎没有帮助。文档甚至提到 setLabelAlignment 仅对标签进行水平对齐(即使这样似乎也不会居中,只是向左或向右)。

顺便说一句,这导致我也尝试将水平对齐设置为居中,但事实证明这更加困难,因为标签不会水平扩展以填充空间(小标签不会扩展以匹配最大的标签)。我可以获得水平居中标签的唯一方法是在显示小部件后显式找到最大标签的宽度,然后将所有其他标签设置为具有相同的宽度......

labels = [layout.itemAt(i*2).widget() for i in range(layout.rowCount())]
max_width = max(label.width() for label in labels)
for w in labels:
    w.setFixedWidth(max_width)
    w.setAlignment(QtCore.Qt.AlignCenter)

结果如下:

我在 QFormLayout 级别是否缺少任何将标签居中的内容?我是否必须制作 QLabels 并设置为扩展或事后打开扩展(如下所示)?感谢您的任何想法!

expand = QtGui.QSizePolicy.Expanding
labels = [layout.itemAt(i*2).widget() for i in range(layout.rowCount())]
for w in labels:
    w.setSizePolicy(expand, expand)

【问题讨论】:

    标签: qt pyqt alignment pyside qlayout


    【解决方案1】:

    “[2] 标签只能左对齐(默认情况下)或右对齐” - 我不相信这是真的。

    您的代码不适合我,所以我无法测试您的确切代码。但是,此方法适用于其他小部件:注意使用 | 来分隔各种位置命令。

    label2.setAlignment(PyQt5.QtCore.Qt.AlignLeft|PyQt5.QtCore.Qt.AlignVCenter)
    

    我知道这是几年前的事了,所以你可能想出了另一种方法,但这种方法对我很有效。

    【讨论】:

    • 我明天会测试一下。问题在于 QFormLayout 对标签布局有一套自以为是的限制,它在内部处理。我认为您展示的行为对于在 QGridLayout 中手动创建的标签非常有意义。当高级便利功能(QFormLayout)没有提供您想要的选项时,这可能只是需要下拉抽象层(到 QGridLayout)的经典案例。感谢您的建议!我的代码仍然有效,因此改进对我仍然有用。
    • 没有问题,我希望这最终会为您解决问题。
    • 这应该是公认的答案。当前接受的答案提出了错误的主张。
    【解决方案2】:

    我认为您的问题没有优雅的解决方案。 来自QFormLayout's source code

    void QFormLayoutPrivate::arrangeWidgets(const QVector<QLayoutStruct>& layouts, QRect &rect)
    {
        // [...]
        if (label) {
            int height = layouts.at(label->vLayoutIndex).size;
            if ((label->expandingDirections() & Qt::Vertical) == 0) {
                /*
                    If the field on the right-hand side is tall,
                    we want the label to be top-aligned, but not too
                    much. So we introduce a 7 / 4 factor so that it
                    gets some extra pixels at the top.
                */
                height = qMin(height,
                          qMin(label->sizeHint.height() * 7 / 4,
                               label->maxSize.height()));
                }
    
       [1]  QSize sz(qMin(label->layoutWidth, label->sizeHint.width()), height);
            int x = leftOffset + rect.x() + label->layoutPos;
       [2]  if (fixedAlignment(q->labelAlignment(), layoutDirection) & Qt::AlignRight)
       [ ]      x += label->layoutWidth - sz.width();
       [ ]  QPoint p(x, layouts.at(label->vLayoutIndex).pos);
            // ### expansion & sizepolicy stuff
    
            label->setGeometry(QStyle::visualRect(layoutDirection, rect, QRect(p, sz)));
        }
        // [...]
    }
    

    我们在这里看到了什么?

    • [1] 标签不会水平拉伸
    • [2] 标签只能左对齐(默认)或右对齐

    因此,您必须以某种方式手动同步标签的宽度(例如设置固定宽度)或放弃QFormLayout 并改用QGridLayout

    【讨论】:

    • 太棒了!感谢您阐明这种行为!在 Python 子类中覆盖该方法会起作用吗?私有化会阻止这种情况吗?不过,尝试重写该方法肯定比仅使用 QGridLayout 更麻烦,所以我认为这是阻力最小的路径。
    • @flutefreak7 不,这个方法不能被覆盖。
    猜你喜欢
    • 1970-01-01
    • 2016-11-02
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    相关资源
    最近更新 更多