Pyqt:使用布局管理器在两个小部件应用程序上强制执行sizeHint()维度

时间:2017-09-22 09:45:55

标签: python layout pyqt qsizepolicy

我有两个小部件,WidgetAWidgetBQDialogWidgetA,水平布局管理器。 我正在尝试执行以下尺寸/调整大小的政策:
对于 WidgetB

  • 水平:宽度应为900,能够缩小(最多100个),并扩展(到任何地方)。
  • 垂直:高度应为600,具有扩展能力(无论如何)。

WidgetA

  • 水平:宽度应固定为600。
  • 垂直:高度应该是600,能够扩展(到任何地方) - 与class WidgetA(QTextEdit): def __init__(self, parent = None): super(WidgetA, self).__init__(parent) #self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding) --> WidgetA width still smaller than 900 #self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.MinimumExpanding) --> WidgetA will be set to minimumSizeHint() #self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) --> not good for me, since I want WidgetA to be able to shrink up to minimumSizeHint().width() #self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.MinimumExpanding) --> not good for me for the same reason - I want WidgetA to be able to shrink up to minimumSizeHint().width() def minimumSizeHint(self): return QSize(100, 600) def sizeHint(self): return QSize(900, 600) class WidgetB(QTextEdit): def __init__(self, parent = None): super(WidgetB, self).__init__(parent) self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) def sizeHint(self): return QSize(600, 600) class MainForm(QDialog): def __init__(self, parent = None): super(MainForm, self).__init__(parent) label_a = QLabel('A') widget_a = WidgetA() label_a.setBuddy(widget_a) label_b = QLabel('B') widget_b = WidgetB() label_b.setBuddy(widget_b) hbox = QHBoxLayout() vbox = QVBoxLayout() vbox.addWidget(label_a) vbox.addWidget(widget_a) widget = QWidget() widget.setLayout(vbox) hbox.addWidget(widget) vbox = QVBoxLayout() vbox.addWidget(label_b) vbox.addWidget(widget_b) widget = QWidget() widget.setLayout(vbox) hbox.addWidget(widget) self.setLayout(hbox) def run_app(): app = QApplication(sys.argv) form = MainForm() form.show() app.exec_() if __name__ == '__main__': run_app() 相同。

但无论我为WidgetA选择哪种尺寸的政策,它仍然不会占用900的宽度 这是一个代码示例:

self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.MinimumExpanding)

我能得到的最接近的是我设置的时间:

WidgetA

WidgetB

enter image description here

似乎WidgetA正在忽略WidgetB的900宽度(消除MainForm诀窍),但我不应受窗口宽度的限制。
什么阻止窗口本身WidgetA)自动水平扩展,以便考虑WidgetB的900宽度和{{1}}的固定600宽度β

1 个答案:

答案 0 :(得分:3)

根据Layout Management上的文章,添加小部件时应用的规则如下:

  
      
  1. 所有小部件最初将根据其QWidget :: sizePolicy()和QWidget :: sizeHint()分配一定的空间。
  2.   
  3. 如果任何小部件设置了拉伸因子,且值大于零,则按比例分配空间   他们的伸展因子(如下所述)。
  4.   
  5. 如果任何小部件的拉伸系数设置为零,则只有在没有其他小部件需要空间时才会获得更多空间。这些,   space首先使用扩展大小策略分配给小部件。
  6.   
  7. 分配的空间小于其最小大小的小部件(如果未指定最小大小,则分配最小大小提示)   他们需要的最小尺寸。 (小部件不必具有最低限度   尺寸或最小尺寸提示,在这种情况下拉伸系数是他们的   决定因素。)
  8.   
  9. 分配了比最大大小更多空间的任何小部件都会分配它们所需的最大大小空间。 (小工具没有   必须有一个最大尺寸,在这种情况下伸展因子是他们的   决定因素。)
  10.   

因此,您可以做的最多是定义sizeHintminimumSizeHint,将拉伸系数设置为大于所有其他系数,并设置大小政策Expanding。但即使有了所有这些东西,似乎布局管理器仍然不能保证在最小尺寸提示较少时遵守尺寸提示。

问题是Expanding的定义不够 足够强大:

  

sizeHint()是一个合理的大小,但小部件可以缩小   仍然有用。小部件可以利用额外的空间,所以它应该   获得尽可能多的空间(例如a的水平方向)   水平滑块)。

无论出于何种原因,如果另一个小部件具有更强的大小策略(例如Fixed),布局管理器似乎优先缩小扩展。从您的示例的角度来看,这看起来是错误的选择,但我想可能还有其他情况更有意义。在Qt4和Qt5中,行为似乎完全相同,所以我不知道它是否应该被视为错误,或者只是实现的怪癖。

我能想出的最简单的解决方法就是强制执行widget_a的大小提示:

class MainForm(QDialog):

    def __init__(self, parent = None):
        ...

        self.setLayout(hbox)

        widget_a.setMinimumSize(widget_a.sizeHint())
        self.adjustSize()
        widget_a.setMinimumSize(widget_a.minimumSizeHint())

(注意:仅在Linux上使用Openbox窗口管理器进行测试)。

PS:另见这个非常相似的问题:Resize window to fit content