设置QFormLayout QLabel的垂直对齐

时间:2016-01-06 23:27:26

标签: qt pyqt alignment pyside qlayout

我使用的是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_()

结果如下:

QFormLayout example with upper-left aligned labels

这是一个通过明确创建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 with vertically expanded labels

我已经尝试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)

结果如下:

enter image description here

QFormLayout级别是否有任何遗漏标签的中心?我是否必须制作QLabel并设置扩展或开启事后扩展(如下所示)?谢谢你的任何想法!

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

2 个答案:

答案 0 :(得分:1)

我不认为你的问题有一个优雅的解决方案。 来自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]标签只能左对齐(默认情况下)或右对齐

所以你必须以某种方式手动同步标签&#39;宽度(例如设置固定的一个)或放弃QFormLayout并使用QGridLayout代替。

答案 1 :(得分:0)

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

您的代码无法为我运行,因此我无法测试您的确切代码。但是,此方法适用于其他窗口小部件:请注意使用|来分隔各种位置命令。

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

我知道这已经有几年历史了,所以您可能想出了另一种方法,但是这种方法对我来说效果很好。