用PyQt4调整对话框大小

10 投票
4 回答
18520 浏览
提问于 2025-04-17 08:51

我有一段代码:

import sys
from PyQt4.QtGui import (QApplication, QHBoxLayout, QVBoxLayout, QDialog,
                                          QFrame, QPushButton, QComboBox)

class Form(QDialog):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)

        moreButton = QPushButton('moreButton')
        moreButton.setCheckable(True)
        resizeButton = QPushButton('Resize')
        combo = QComboBox()
        combo.addItems(['item1', 'item2'])

        layout1 = QHBoxLayout()
        layout1.addWidget(moreButton)
        layout1.addWidget(resizeButton)

        layout2 = QHBoxLayout()
        layout2.addWidget(combo)
        self.frame = QFrame()
        self.frame.setLayout(layout2)
        self.frame.hide()

        layout3 = QVBoxLayout()
        layout3.addLayout(layout1)
        layout3.addWidget(self.frame)

        moreButton.toggled.connect(self.frame.setVisible)
        moreButton.clicked.connect(self.method)
        resizeButton.clicked.connect(self.method)

        self.setLayout(layout3)
        self.resize(630, 50)

    def method(self):
        if self.frame.isVisible():           
            self.resize(630, 150)
        else:
            self.resize(630, 250)

app = QApplication(sys.argv)
form = Form()
form.show()
app.exec_()

我运行这段代码,当点击moreButton时,ComboBox会出现或消失。对话框的大小也会随之变化。但是,如果我把方法改成:

def method(self):
    if self.frame.isVisible():           
        self.resize(630, 150)
    else:
        self.resize(630, 50)

(这样可以在ComboBox隐藏时设置初始大小)调整大小就不管用了。不过,如果我点击resizeButton——这个按钮连接的是同一个方法——调整大小就能正常工作。

我知道还有其他方法可以达到这个效果(比如使用layout.setSizeConstraint(QLayout.SetFixedSize)),但我想明确地声明大小。

我哪里做错了?

4 个回答

2

这个问题似乎是因为事件处理的顺序出了问题。

这里有一个简单的解决办法:

def method(self):
    app.processEvents()
    if self.frame.isVisible():           
        self.resize(630, 150)
    else:
        self.resize(630, 50)
3

这个问题和答案对我来说很有帮助:我想让一个QDialog的大小自动适应里面的内容,这个内容是一个QLabel,内容的大小是变化的。同时,我还想避免在QDialog的边框出现双箭头光标。虽然我把对话框的大小设置成了固定的,但双箭头还是会出现,尽管它是不能被调整大小的(根本不会动)。而且,虽然里面的布局确实会自动调整大小,但如果我在布局上使用SetFixedSize(真是意外),那么那些烦人的双箭头就消失了。

QDialog: QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
QLayout: setSizeConstraint(QLayout.SetFixedSize)
QLabel:  QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

...现在这个对话框的大小能够适当地根据标签里的内容来调整,但对话框本身看起来是不能被用户调整大小的,这对显示信息和错误消息来说是好的。

这让我觉得有点反直觉,所以我觉得值得在这里分享给其他人。
再多说一点...

self.label = QtGui.QLabel(self)
self.label.sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
self.label.setSizePolicy(self.label.sizePolicy)
self.label.setMinimumSize(QtCore.QSize(450, 40))
self.label.setWordWrap(True)

self.verticalLayout = QtGui.QVBoxLayout(self)
# get rid of overall dialog resize arrows
self.verticalLayout.setSizeConstraint(QtGui.QLayout.SetFixedSize)  # no resize arrows
self.verticalLayout.addWidget(self.label)
8

我猜你的问题是,你在隐藏一些东西之后,试图调整 QDialog 的大小,但它还没来得及重新调整大小。也就是说,当你调用 resize 的时候,它的 minimumSize 还在确保按钮和下拉框是可见的。等你过了一段时间再调用,它的 minimumSize 就调整好了,这样就能正常响应了。

一个简单的解决办法是在调整大小之前手动设置 minimumSize

def method(self):
    if self.frame.isVisible():
        # uncomment below, if you like symmetry :)
        # self.setMinimumSize(630, 150)
        self.resize(630, 150)
    else:
        self.setMinimumSize(630, 50)
        self.resize(630, 50)

不过,如果是我来处理这个问题,我会把调整大小的管理交给布局,并使用 sizeConstraint。反正这些布局就是为了这个目的的。

撰写回答