How do I stop a custom widget from expanding in PyQt5?

孤者浪人 提交于 2021-01-29 08:35:53

问题


I'm trying to make a widget which contains many other widgets and I keep having problems with resizing the window: the widget keeps expanding even if I "tell" it not to. Here is my minimal example:

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

This code does work however if I resize the window then all the buttons and labels get spread out over the screen which is not what I want.

I've tried:

  • Setting a fixed size: doesn't work because the label text can be different lengths and I want the widget to resize accordingly (but stay as small as possible)

  • self.setFixedSize(self.size()) doesn't do anything and sometimes makes it worse

  • self.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) or any other size policy seems to do nothing

TL;DR I want my widget to shrink even if there's empty space but I don't want to set a fixed size.

EDIT:

I have partially solved the problem by passing in alignment=QtCore.Qt.AlignLeft to all the self.layout.addWidget calls. It doesn't totally get rid of the problem however it may be a step in the right direction.


回答1:


If you want to keep those widgets as small as possible, you can add a row and column stretch to the layout, set for a row/column index greater than the most bottom-right layout coordinate used.

In your case, you have two rows and two columns, so it's enough to set the stretch for the third row and column:

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

Obviously, you can set it for a very high index, so that if you have to add more widgets you don't have to care about it.

If you want to keep those widgets in the center, just add them starting from the second row and column and set the row/column stretch for the first row/column too:

    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)

Note that you can also use the size policy, but you have to use Maximum, not Minimum, and you also need to add widgets with the correct alignment.




回答2:


I got same issue. I resolved the issue by setting the values of minimum and maximum size to equal like both to 100

If you want to shrink the widget set minimum to 0 and set maximum value to the size you want start the display. It will not expand but shrink




回答3:


From what you are describing it seems you just don't want to use a layout.

Make a widget with a layout to hold the buttons and label. Place this widget in the main window without using a layout, instead place with setGeometry.

Something like this,

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

Notice that not using a layout is, in most cases, not advised as it makes managing the window harder.



来源:https://stackoverflow.com/questions/62657281/how-do-i-stop-a-custom-widget-from-expanding-in-pyqt5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!