3

我有两个小部件彼此相邻,WidgetA并且WidgetB在 aQDialog上具有水平布局管理器。
我正在尝试执行以下大小/调整大小策略:
对于WidgetA

  • 水平方向:宽度应为 900,并且可以收缩(最多 100)和扩展(任意)。
  • 垂直:高度应该是 600,并且可以扩展(到任何东西)。

对于WidgetB

  • 水平:宽度应固定为 600。
  • 垂直:高度应为 600,具有扩展(到任何)的能力 - 与WidgetA.

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

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

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

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

WidgetA

在此处输入图像描述

似乎是从900 宽度WidgetB中咬了一口(消除就可以了),但我不应该受到窗口宽度的限制。 是什么阻止了窗口本身()自动水平扩展以考虑900 宽度和600 固定宽度?WidgetAWidgetB
MainFormWidgetAWidgetB

4

1 回答 1

5

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

  1. 所有小部件最初将根据它们的 QWidget::sizePolicy() 和 QWidget::sizeHint() 分配一定量的空间。
  2. 如果任何小部件设置了拉伸因子,其值大于零,则它们将按其拉伸因子的比例分配空间(如下所述)。
  3. 如果任何小部件将拉伸因子设置为零,则只有在没有其他小部件需要空间时,它们才会获得更多空间。其中,空间首先分配给具有扩展大小策略的小部件。
  4. 分配的空间小于其最小尺寸(或最小尺寸提示,如果没有指定最小尺寸)的任何小部件都被分配了它们所需的最小尺寸。(小部件不必有最小尺寸或最小尺寸提示,在这种情况下,拉伸因子是它们的决定因素。)
  5. 分配的空间超过其最大尺寸的任何小部件都将分配它们所需的最大尺寸空间。(小部件不必有最大尺寸,在这种情况下,拉伸因子是它们的决定因素。)

所以你能做的最多就是定义sizeHintand minimumSizeHint,设置一个比所有其他因子都大的拉伸因子,并设置一个 size-policy Expanding。但即使所有这些东西都到位,布局管理器似乎仍然不能保证在最小尺寸提示较小时遵守尺寸提示。

问题是 的定义Expanding不够

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

无论出于何种原因,如果另一个小部件具有更强的尺寸策略(例如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:另请参阅这个非常相似的 SO 问题:Resize window to fit content

于 2017-09-24T18:55:16.987 回答