Due to its nature, a QMessageBox should never allow resizing. If you need that, you should probably use a QDialog instead.
That said, the fixed size restraint is caused by the internal layout, which is also replaced any time relevant aspects of the dialog change (buttons, [un]setting detailed text, etc.).
Since the layout management is completely internal, and it always resets the fixed size of the dialog, the solution is to watch for relevant events, specifically LayoutRequest
(which is called whenever the layout needs to be redone) and Resize
and override the maximum size.
With a subclass, the solution is pretty simple:
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)
Alternatively, with an event filter:
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)
Note: none of the above will work with the static methods of QMessageBox, since they create a private instance.