2016-01-06 93 views
1

我使用PySide/PyQt的,但是這是一個普通的Qt問題的設置垂直對齊方式。QFormLayout QLabel

有沒有辦法設置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水平將圍繞標籤?我是否必須製作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) 

回答

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]標籤只能左對齊(默認)或右

所以你必須要麼不知何故手動同步標籤的寬度(例如設置固定的一個)或者放棄QFormLayout並使用QGridLayout代替。

+0

太棒了!感謝您澄清此行爲!在Python子類中覆蓋該方法是否工作?它是私人防止呢?儘管嘗試重寫該方法肯定比使用QGridLayout更麻煩,但我認爲這是阻力最小的路徑。 – flutefreak7

+0

@ flutefreak7不可以,這個方法不能被覆蓋。 –