如何允许在PyQt4中调整QMessageBox的大小
我正在使用QMessageBox这个很不错的功能,可以选择性地向用户显示详细信息。不过,展开后的窗口还是比较小,大家通常会想要调整窗口大小,以便能看到更多的细节。即使我设置了我认为合适的选项,窗口还是不允许调整大小。
下面是相关的PyQt4代码片段:
mb = QMessageBox()
mb.setText("Results written to '%s'" % filename)
mb.setDetailedText(str(myData))
mb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
mb.setSizeGripEnabled(True)
我是不是漏掉了什么步骤?或者说这根本就不可能?
5 个回答
2
由于QMessageBox的特性,它不应该允许调整大小。如果你需要可以调整大小的对话框,建议使用QDialog。
说到这里,QMessageBox的固定大小是因为它内部的布局造成的,每当对话框的某些部分(比如按钮、详细文本等)发生变化时,这个布局就会被替换。
由于布局管理完全在内部进行,并且它总是会重置对话框的固定大小,所以解决办法是关注相关的事件,特别是LayoutRequest
(每当需要重新布局时会被调用)和Resize
,并覆盖最大大小。
如果你创建一个子类,解决方案就比较简单:
class ResizableMessageBox(QtWidgets.QMessageBox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setSizeGripEnabled(True)
def event(self, event):
if event.type() in (event.LayoutRequest, event.Resize):
if event.type() == event.Resize:
res = super().event(event)
else:
res = False
details = self.findChild(QtWidgets.QTextEdit)
if details:
details.setMaximumSize(16777215, 16777215)
self.setMaximumSize(16777215, 16777215)
return res
return super().event(event)
另外,你也可以使用事件过滤器来实现:
class Something(QWidget):
# ...
def showMessageBox(self):
mb = QtWidgets.QMessageBox()
mb.setSizeGripEnabled(True)
mb.setWindowTitle('Hello')
mb.setText('I am a message box')
mb.setDetailedText('very long text ' * 10)
mb.setProperty('resizable', True)
mb.installEventFilter(self)
mb.exec()
def eventFilter(self, obj, event):
if (isinstance(obj, QtWidgets.QMessageBox)
and obj.property('resizable')
and event.type() in (event.LayoutRequest, event.Resize)):
if event.type() == event.Resize:
obj.event(event)
details = obj.findChild(QtWidgets.QTextEdit)
if details:
details.setMaximumSize(16777215, 16777215)
obj.setMaximumSize(16777215, 16777215)
return True
return super().eventFilter(obj, event)
注意:以上方法都不适用于QMessageBox的静态方法,因为它们会创建一个私有实例。
5
如果你想做一个可以调整大小的消息框,请看看下面的代码是否适合你:
class MyMessageBox(QtGui.QMessageBox):
def __init__(self):
QtGui.QMessageBox.__init__(self)
self.setSizeGripEnabled(True)
def event(self, e):
result = QtGui.QMessageBox.event(self, e)
self.setMinimumHeight(0)
self.setMaximumHeight(16777215)
self.setMinimumWidth(0)
self.setMaximumWidth(16777215)
self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
textEdit = self.findChild(QtGui.QTextEdit)
if textEdit != None :
textEdit.setMinimumHeight(0)
textEdit.setMaximumHeight(16777215)
textEdit.setMinimumWidth(0)
textEdit.setMaximumWidth(16777215)
textEdit.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)
return result
这是调用消息框的方式:
mb = MyMessageBox()
mb.setText("Results written to '%s'" % 'some_file_name')
mb.setDetailedText('some text')
mb.exec_()
这个解决方案来自于 这里
希望这对你有帮助,祝好
6
这是我会使用的解决方案。虽然这并不会让对话框可以调整大小,但它会在详细信息框可见时,让对话框自动调整到一个合适的大小。我毫不掩饰地借鉴了serge_gubenko的答案中的一些想法。即使你更想实现他的调整大小功能,我还是谦虚地提供了一些其他的改进建议。
# Safe since everything in the namespace begins with 'Q'
from PyQt4.QtGui import *
class MyMessageBox(QMessageBox):
# This is a much better way to extend __init__
def __init__(self, *args, **kwargs):
super(MyMessageBox, self).__init__(*args, **kwargs)
# Anything else you want goes below
# We only need to extend resizeEvent, not every event.
def resizeEvent(self, event):
result = super(MyMessageBox, self).resizeEvent(event)
details_box = self.findChild(QTextEdit)
# 'is not' is better style than '!=' for None
if details_box is not None:
details_box.setFixedSize(details_box.sizeHint())
return result