如何在 PyQt5(QGridLayout) 中调整我的小部件的大小

How to resize my widgets in PyQt5(QGridLayout)

我有一个问题。我开始学习PyQt5,我想做一个计算器。所以我学会了如何充满激情 我的小部件 QGridLayout,但我无法更改小部件的大小。有些小部件比其他小部件大,我不明白。我尝试了不同的方法,比如 (resize, setGeometry) 但它没有用。我也想调整我的 QLineEdit 变量的大小,但我不能。这是我的问题的代码和图片:

import PyQt5.QtWidgets as qwd
import PyQt5.QtGui as qtg

class CreateWindow(qwd.QWidget):
    # create window
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle('calculator')
        self.setWindowIcon(qtg.QIcon('calculator.png'))
        self.setStyleSheet('background: #FAEBD7;')
        # self.setFixedWidth(300)
        # self.setFixedHeight(170)

        # show result
        self.text = '0'

        self.UIcomponents()

        self.show()

    def UIcomponents(self):
        # layout

        grid = qwd.QGridLayout()
        

        # show numbers
        self.resultText = qwd.QLineEdit(self.text)
        self.resultText.setReadOnly(True)
        self.resultText.setStyleSheet('background: #FFFAFA;')

        # buttons
        self.but9 = qwd.QPushButton('9')
        self.but8 = qwd.QPushButton('8')
        self.but7 = qwd.QPushButton('7')
        self.but6 = qwd.QPushButton('6')
        self.but5 = qwd.QPushButton('5')
        self.but4 = qwd.QPushButton('4')
        self.but3 = qwd.QPushButton('3')
        self.but2 = qwd.QPushButton('2')
        self.but1 = qwd.QPushButton('1')
        self.but0 = qwd.QPushButton('0')
        self.but_add = qwd.QPushButton('+')
        self.but_decreas = qwd.QPushButton('-')
        self.but_multiply = qwd.QPushButton('*')
        self.but_devide = qwd.QPushButton('/')     
        self.but_equal = qwd.QPushButton('=')

        # positionate the buttons
        grid.addWidget(self.resultText, 0, 0)
        grid.addWidget(self.but9, 1, 2)
        grid.addWidget(self.but8, 1, 1)
        grid.addWidget(self.but7, 1, 0)
        grid.addWidget(self.but6, 2, 2)
        grid.addWidget(self.but5, 2, 1)
        grid.addWidget(self.but4, 2, 0)
        grid.addWidget(self.but3, 3, 2)
        grid.addWidget(self.but2, 3, 1)
        grid.addWidget(self.but1, 3, 0)
        grid.addWidget(self.but0, 4, 0)

        # buttons for operation
        self.but_devide.setStyleSheet('background: #7FFFD4')
        grid.addWidget(self.but_devide, 1, 4)
        self.but_multiply.setStyleSheet('background: #7FFFD4')
        grid.addWidget(self.but_multiply, 2, 4)
        self.but_add.setStyleSheet('background: #7FFFD4')
        grid.addWidget(self.but_add, 3, 4)
        self.but_decreas.setStyleSheet('background: #7FFFD4')
        grid.addWidget(self.but_decreas, 4, 4)
        self.but_equal.setStyleSheet('background: #008B8B')
        grid.addWidget(self.but_equal, 4, 2)

        # connect buttons
        self.but9.clicked.connect(lambda state, number = '9': self.show_result(number))
        self.but8.clicked.connect(lambda state, number = '8': self.show_result(number))
        self.but7.clicked.connect(lambda state, number = '7': self.show_result(number))
        self.but6.clicked.connect(lambda state, number = '6': self.show_result(number))
        self.but5.clicked.connect(lambda state, number = '5': self.show_result(number))
        self.but4.clicked.connect(lambda state, number = '4': self.show_result(number))
        self.but3.clicked.connect(lambda state, number = '3': self.show_result(number))
        self.but2.clicked.connect(lambda state, number = '2': self.show_result(number))
        self.but1.clicked.connect(lambda state, number = '1': self.show_result(number))
        self.but0.clicked.connect(lambda state, number = '0': self.show_result(number))
        self.but_decreas.clicked.connect(lambda state, oper = '-': self.chose_oper(oper))
        self.but_add.clicked.connect(lambda state, oper = '+': self.chose_oper(oper))
        self.but_multiply.clicked.connect(lambda state, oper = '*': self.chose_oper(oper))
        self.but_devide.clicked.connect(lambda state, oper = '/': self.chose_oper(oper))

        self.setLayout(grid)

    def show_result(self, number):
        if len(self.text) != 20:
            print(len(self.text))
            if self.text[0] == '0':
                self.text = ''
            self.text += number
            self.resultText.setText(str(self.text))
            
    def chose_oper(self, oper):
        if self.text[0] != '0':
                self.text += oper
        self.resultText.setText(str(self.text))

def create_app():
    app = qwd.QApplication([])
    wind = CreateWindow()
    # set app style
    app.setStyle('Fusion')

    app.exec_()

create_app()

tl;博士

在将小部件添加到网格布局时选择适当的列跨度

    grid.addWidget(self.resultText, 0, 0, 1, 5)

说明

布局管理器的要点在于它管理布局

基于设置它的小部件及其管理的所有项目(小部件甚至其他嵌套布局),考虑所有约束(可能minimum/maximum大小),提示(首选大小)和大小策略(是否以及如何调整小部件的大小),然后它决定这些项目应该放置在哪里以及它们有多大。

考虑到所有这些,您可以理解尝试手动调整这些小部件的大小没有意义,因为布局会尽快覆盖它[1]

大多数小部件会根据他们的 sizeHint 建议尽可能多地使用布局给他们的 space,如果有更多 space 可用,他们 可以尝试使用它。按钮的宽度是这样,但它们的高度不是这样(通常是固定的)。

当 window 被 映射(第一次显示)时,布局会考虑以上所有因素,包括尺寸提示,并尝试使用允许所有这些提示得到尊重的大小。事实上,如果您尝试将 window 的大小调整到尽可能小的大小,您会发现所有按钮(和行编辑)很可能会获得相同的大小。

您正在使用 网格 布局,它允许将项目放在网格的 单元格 中:行和列。由于您将 QLineEdit 放在第一列,并且该小部件的默认大小提示比按钮宽,结果是当 window 第一次显示时,第一列将使用该宽度,并且由于按钮适应它们的宽度为可用 space,第一列中的宽度将显示为与行编辑一样宽。

网格布局允许使用 spanning(参见 documentation,这是一种让一个项目占据多个单元格行 and/or 列的方法。考虑到你的程序的目的,如果它占据整个水平 space,那行编辑可能看起来更好,并且因为你使用 5 列(操作按钮在第 4 列,索引总是从 0 开始)那是我们如何得到上面的行:

    grid.addWidget(self.resultText, 0, 0, 1, 5)

其中表示:将小部件添加到第 0 行和第 0 列,并使其只占一行但占五列。
如果未给出 span 参数,则它们隐式仅占用一行和一列。请注意,即使您只对一个跨度“方向”感兴趣,两个 跨度参数也是必需的(它们不是关键字参数)。

[1] 可以使用 resizesetGeometry, 布局完成后;但是尝试这样做没有什么意义:一旦 window 以任何方式(从用户或系统)调整大小,布局将覆盖那些手动尝试。如果您尝试在 before 显示 window 时发生这种情况:当小部件第一次显示时,它还会收到 resize 事件,如果该小部件有布局,它会自动通知该布局,以便它可以执行所有计算。