设置QFormLayout QLabel的垂直对齐方式 [英] Set Vertical Alignment of QFormLayout QLabel

查看:135
本文介绍了设置QFormLayout QLabel的垂直对齐方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



有没有一种方法可以设置QFormLayout,使标签垂直居中而不会必须明确创建QLabel,并将其纵向尺寸政策设置为首先扩展?当第2列中的小部件比我的标签高时,我希望标签与小部件垂直居中,而不是与其顶部对齐...



演示问题的示例脚本。我将标签涂成红色以更好地展示其尺寸行为。

 从PySide导入QtCore,QtGui 

app = QtGui.QApplication([])

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

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

编辑器1 = 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)

小部件。 show()

app.exec_()

结果如下:





以下示例通过显式创建QLabel并为其提供扩展尺寸策略来展示所需的结果:

 从PySide导入QtCore,QtGui 

app = QtGui.QApplication([])

小部件= 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(展开,展开)

label2 = QtGui.QLabel('较长名称输入')
label2.setSizePolicy(展开,展开)

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

widget.set布局(布局)

widget.show()

app.exec_()

这就是结果...





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



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

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

这会导致以下结果:



  void QFormLayoutPrivate :: arrangeWidgets(const QVector< QLayoutStruct>& layouts,QRect& rect)
{
// [...]
if(label){
int height = layouts.at(label-> ; vLayoutIndex).size;
if(((label-> expandingDirections()& Qt :: Vertical)== 0){
/ *
如果右侧的字段很高,则
我们希望标签在顶部对齐,但
不太高。因此,我们引入7/4因子,以便
在顶部获得更多像素。
* /
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]如果(fixedAlignment(q-> labelAlignment(),layoutDirection)& Qt :: AlignRight)
[] x + = label-> layoutWidth-sz.width();
[] QPoint p(x,layouts.at(label-> vLayoutIndex).pos);
// ###扩展& sizepolicy东西

标签-> setGeometry(QStyle :: visualRect(layoutDirection,rect,QRect(p,sz)));
}
// [...]
}

我们在这里看到什么?




  • [1]标签不会水平拉伸

  • [2]标签只能左对齐(默认情况下)或右对齐



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


I'm using PySide/PyQt, but this is a general Qt question.

Is there a way to set up a QFormLayout so that labels are centered vertically without having to explicitly create the QLabel's and set their vertical size policy to expanding first? When the widget in column 2 is taller than my label, I want my label to be centered vertically with the widget, rather than aligned with it's top...

Here's an example script that demonstrates the problem. I've colored the labels red to better demonstrate their size behavior.

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_()

Here's the outcome:

Here's an example that demonstrates the desired result by explicitly creating QLabel's and giving them an expanding size policy:

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_()

And here's that outcome...

I've tried QFormLayout.setLabelAlignment() which doesn't appear to help. The docs even mention that setLabelAlignment only does the horizontal alignment of the labels (and even then doesn't appear to do centered, just left or right).

As an aside, this lead me to also try to set the horizontal alignment to centered, but that proved even harder since the labels don't expand horizontally to fill the space (small labels don't expand to match the biggest label). The only way I could get horizontally centered labels was to explicitly find the width of the biggest label, after showing the widget, then set all other labels to have the same width...

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)

Which results in this:

Is there anything I'm missing at the QFormLayout level that will center the labels? Do I have to make QLabels and set to expanding or turn on expanding after the fact (like below)? Thanks for any ideas!

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

解决方案

I don't think there is an elegant solution to your problem. From 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)));
    }
    // [...]
}

What do we see here?

  • [1] Labels do not stretch horizontally
  • [2] Labels can only be aligned left (by default) or right

So you have to either somehow manually synchronize labels' widths (e.g. set fixed one) or abandon QFormLayout and use QGridLayout instead.

这篇关于设置QFormLayout QLabel的垂直对齐方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆