【问题标题】:How do I stop a custom widget from expanding in PyQt5?如何阻止自定义小部件在 PyQt5 中扩展?
【发布时间】:2020-10-20 17:55:41
【问题描述】:

我正在尝试制作一个包含许多其他小部件的小部件,但我一直在调整窗口大小时遇到​​问题:即使我“告诉”它不要这样做,小部件也会继续扩展。这是我的最小示例:

from PyQt5 import QtWidgets, QtGui, QtCore

class CustomWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.layout  = QtWidgets.QGridLayout()
        self.button1 = QtWidgets.QPushButton("Button A")
        self.button2 = QtWidgets.QPushButton("Button B")
        self.label1  = QtWidgets.QLabel("Long label that can span multiple columns")

        self.layout.addWidget(self.button1, 0, 0)
        self.layout.addWidget(self.button2, 0, 1)
        self.layout.addWidget(self.label1, 1, 0, 1, 2)
        self.setLayout(self.layout)


class App(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.cw = CustomWidget()
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.cw)

        self.setLayout(self.layout)
        self.show()

QtWidgets.QApplication.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
app = QtWidgets.QApplication([])
win = App()
status = app.exec_()

此代码确实有效,但是如果我调整窗口大小,那么所有按钮和标签都会散布在屏幕上,这不是我想要的。

我试过了:

  • 设置固定大小:不起作用,因为标签文本可以有不同的长度,我希望小部件相应地调整大小(但尽可能小)

  • self.setFixedSize(self.size()) 不做任何事情,有时会让事情变得更糟

  • self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) 或任何其他尺寸政策似乎无济于事

TL;DR 我希望我的小部件即使有空白空间也可以缩小,但我不想设置固定大小。

编辑:

我已经部分通过将alignment=QtCore.Qt.AlignLeft 传递给所有self.layout.addWidget 调用解决了这个问题。它并不能完全解决问题,但它可能是朝着正确方向迈出的一步。

【问题讨论】:

  • 您的问题有点不清楚,尤其是这个:“即使有空白空间,我也希望我的小部件缩小”。你的意思是?您是否尝试设置最大尺寸(或宽度)?
  • @musicamante 我已经尝试设置一个固定/最大尺寸(它们实际上都是一样的)但是 UI 的某些元素可以改变尺寸(即标签文本可能更长),因此我需要动态调整大小。
  • 我还是不太明白你想要达到什么目的。你能提供一些预期行为的图片吗?
  • @musicamante 当然,我会制作一张图片并将其上传到 imgur 或其他地方
  • @musicamante imgur.com/a/aNp9aMp

标签: python qt pyqt pyqt5 qt5


【解决方案1】:

如果您想让这些小部件尽可能小,您可以在布局中添加行和列拉伸,设置为大于使用的最右下角布局坐标的行/列索引。

在您的情况下,您有两行和两列,因此设置第三行和第三列的拉伸就足够了:

    self.layout.setColumnStretch(2, 1)
    self.layout.setRowStretch(2, 1)

显然,您可以将其设置为非常高的索引,这样如果您必须添加更多小部件,您就不必关心它。

如果您想将这些小部件保持在中心,只需从第二行和第二列开始添加它们,并为第一行/列设置行/列拉伸:

    self.layout.setColumnStretch(0, 1)
    self.layout.setRowStretch(0, 1)
    self.layout.addWidget(self.button1, 1, 1)
    self.layout.addWidget(self.button2, 1, 2)
    self.layout.addWidget(self.label1, 2, 1, 1, 2)
    self.layout.setColumnStretch(3, 1)
    self.layout.setRowStretch(3, 1)

请注意,您也可以使用尺寸策略,但您必须使用Maximum,而不是Minimum,并且您还需要添加对齐正确的小部件。

【讨论】:

  • 哇,谢谢你,它可以工作,而且除了之前有效的答案有一个不需要的副作用,我不能使用布局,这让事情变得更难。我想我会接受这个代替
【解决方案2】:

我遇到了同样的问题。我通过将最小和最大大小的值设置为都等于 100 解决了这个问题

如果您想缩小小部件,请将最小值设置为 0,并将最大值设置为您想要开始显示的大小。不会扩大,只会缩小

【讨论】:

  • 如果您想缩小小部件,请将最小值设置为 0,并将最大值设置为您想要开始显示的大小。它不会扩大但会缩小
  • 请注意,将最小和最大大小设置为相同的值与使用setFixedSize 相同。
  • 这里的问题是我不想定义大小,因为文本(以及我实际设计中的其他内容)会改变大小。我想让它扩展,但不是绝对必要的
【解决方案3】:

根据您的描述,您似乎只是不想使用布局。

制作一个带有布局的小部件来保存按钮和标签。将此小部件放置在主窗口中而不使用布局,而是使用 setGeometry 放置。

类似的,

from PyQt5 import QtWidgets, QtGui, QtCore

class CustomWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.resize(400, 100)
        
        # Create a widget to hold your buttons
        self.fixwidget = QtWidgets.QWidget(self)
        
        self.layout  = QtWidgets.QGridLayout()
        self.button1 = QtWidgets.QPushButton("Button A")
        self.button2 = QtWidgets.QPushButton("Button B")
        self.label1  = QtWidgets.QLabel("Long label that can span multiple columns")

        self.layout.addWidget(self.button1, 0, 0)
        self.layout.addWidget(self.button2, 0, 1)
        self.layout.addWidget(self.label1, 1, 0, 1, 2)
        
        # set the layout inside the widget
        self.fixwidget.setLayout(self.layout) 
        
        # place the widget with setGeometry
        height = self.fixwidget.sizeHint().height()
        width = self.fixwidget.sizeHint().width()
        xpos, ypos = 5, 5
        self.fixwidget.setGeometry(QtCore.QRect(xpos, ypos, width, height))


QtWidgets.QApplication.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
app = QtWidgets.QApplication([])
win = CustomWidget()
win.show()
status = app.exec_()

请注意,在大多数情况下,不建议使用布局,因为这会使管理窗口变得更加困难。

【讨论】:

  • 谢谢!这已经解决了这个问题(我会在一秒钟内接受它)但是有一个问题:在我的实际代码中,我有一个带有图像的标签。图像不断被截断(也许 sizeHint 没有考虑图像大小?)如果你知道如何解决这个问题,那就太好了
  • 抱歉,已解决(我的行和列弄错了!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 1970-01-01
  • 2022-07-02
  • 1970-01-01
相关资源
最近更新 更多