如何允许在 PyQt4 中调整 QMessageBox 的大小
Posted
技术标签:
【中文标题】如何允许在 PyQt4 中调整 QMessageBox 的大小【英文标题】:How to allow resizing of QMessageBox in PyQt4 【发布时间】:2010-04-16 18:38:19 【问题描述】:我正在使用 QMessageBox 中的好功能来选择性地向用户显示详细的文本。然而,扩展后的窗口仍然很小,人们会立即尝试调整窗口大小,以便看到更多细节。即使设置了我认为正确的设置,它也不允许调整大小。
这里是PyQt4的相关sn-p代码:
mb = QMessageBox()
mb.setText("Results written to '%s'" % filename)
mb.setDetailedText(str(myData))
mb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
mb.setSizeGripEnabled(True)
我是否错过了一个步骤和/或这是否可能?
【问题讨论】:
你的意思是QMessageBox在显示的时候还不够大,不能显示你的内容(比如东西被截断了)? 对不起,我不清楚。我的意思是详细的文本仅限于 small 文本区域(带有滚动条)。可见,但从用户的角度来看并不令人愉快。如果QMessageBox
可以根据用户的需要手动调整大小,它将大大改善整体体验。即使调用了setSizePolicy()
和setSizeGripEnabled()
,仍然无法调整窗口大小。
您尝试过最小扩展尺寸策略吗?除此之外,检查一下maximumSize 的设置。您可能需要继承 QMessageBox 并重新实现 sizeHint() 以返回您想要的内容。我一直发现有一些巫术涉及让***小部件根据其内容适当地重新调整自己的大小。您可以尝试的另一件事是设置布局的大小约束:mb.layout()->setSizeConstraint(QLayout::SetMaximumSize)
(啊,那是 c++ - 不熟悉 python 语法)
【参考方案1】:
如果您想制作一个可调整大小的消息框,请检查以下代码是否适合您:
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_()
解决方案取自here
希望这会有所帮助,问候
【讨论】:
这绝对是在正确的轨道上(可惜它必须在事件处理程序中完成)。对话框现在确实会调整大小,但所有调整大小都会转到顶部的标签,而不是文本框。我花了大约半个小时来设置其他组件的sizePolicy
和底层布局的rowStretch
,但没有进一步了解。这绝对比我拥有的要好。如果我弄清楚如何为文本区域提供所有额外的垂直空间,我会发布后续内容。
@serge_gubenko 当我按下对话框上的最大化按钮(按下“显示详细信息”按钮时显示),对话框立即最大化,然后立即恢复正常(并移动到屏幕的左上角)。知道如何修复最大化按钮的工作吗?
这似乎是迄今为止最好的解决方案。但是,每次单击“显示详细信息”/“隐藏详细信息”按钮时,它都会调整为原始的小尺寸。似乎QMessageBox
内部有一个updateSize()
方法正在计算大小,但覆盖它并没有任何区别,至少在 PyQt 中是这样。
我尝试在使用手柄拖动和调整大小时打印出所有事件类型。通过评论一些事件可以正常工作,最后我只剩下一个:QEvent::CursorChange 来处理。【参考方案2】:
这是我会使用的解决方案。这不会使对话框可调整大小,但会在详细信息框可见时使对话框自身更改为合理的大小。我毫不掩饰地从 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
【讨论】:
这在 linux 上根本不起作用。但即使它确实有效,它也不会回答这个问题,因为它不会使消息框可调整大小。 (PS:在这个例子中覆盖__init__
是完全多余的)。【参考方案3】:
这可行,但仅在 Gnome 2 下的 Linux 上进行了测试。它只在水平方向调整大小,除非打开“显示详细信息”文本,在这种情况下,它会在两个方向上调整大小。 “显示详细信息”按钮仍会将其重置为初始大小,这取决于您的 pov,这是一个功能还是一个错误:
bool MyMessageBox::event(QEvent* e)
bool result = QMessageBox::event(e);
// force resizing back on, QMessageBox keeps turning it off:
if (maximumWidth() != QWIDGETSIZE_MAX)
QTextEdit *textEdit = findChild<QTextEdit*>();
if (textEdit && textEdit->isVisible())
textEdit->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
textEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
else
setMaximumWidth(QWIDGETSIZE_MAX);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
return result;
【讨论】:
【参考方案4】:一段时间过去了,但问题仍然有效。
我做了以下实现,在 OSX 和 PySide6 上运行良好,但在其他系统上没有测试。
class MyMessageBox(QMessageBox):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._width = 150 # default
self.setSizeGripEnabled(True)
def setWidth(self, width):
self._width = width
def resizeEvent(self, event):
_result = super().resizeEvent(event)
self.setFixedWidth(self._width)
_text_box = self.findChild(QTextEdit)
if _text_box is not None:
# get width
_width = int(self._width - 50) # - 50 for border area
# get box height depending on content
_font = _text_box.document().defaultFont()
_fontMetrics = QFontMetrics(_font)
_textSize = _fontMetrics.size(0, details_box.toPlainText(), 0)
_height = int(_textSize.height()) + 30 # Need to tweak
# set size
_text_box.setFixedSize(_width, _height)
return _result
通话结束:
_msg_box = MyMessageBox(parent=self)
_msg_box.setIcon(icon)
_msg_box.setText(title_text)
_msg_box.setInformativeText(message)
_msg_box.setDetailedText(detailed_text)
# define a reference width and apply it
_width = int(self.geometry().width() / 2.5)
_msg_box.setWidth(_width)
_msg_box.exec()
这样,默认宽度设置为 150,但可能会通过 setWidth 方法进行更改。高度是自动设置的。 如果提供了详细的文本,则文本框的宽度会比消息框本身的总宽度小一点(- 50),高度取决于内容。
注意我没有在文本框中使用较大的内容。
【讨论】:
以上是关于如何允许在 PyQt4 中调整 QMessageBox 的大小的主要内容,如果未能解决你的问题,请参考以下文章
如何用鼠标动态调整 QHBoxLayout 和 QGraphicsView 大小? (Python,Pyqt4)
PyQt4:如何/何时从 QTabWidget 的子类发出自定义信号?