[PyQt] QMdiArea persistence issue with closed windows
Hans-Peter Jansen
hpj at urpla.net
Wed Oct 13 22:43:04 BST 2010
On Wednesday 13 October 2010, 21:30:08 Phil Thompson wrote:
> On Wed, 13 Oct 2010 15:44:58 +0200, "Hans-Peter Jansen"
> <hpj at urpla.net>
>
> wrote:
> > Hi Phil,
> >
> > while looking at dynamic resizing widgets on irc, David Boddie
> > created a
> >
> > small script, that I improved a little bit, which shows a small bug
> > with mdi windows. According to the doc of QMdiArea::addSubWindow,
> > closing windows should stay hidden, but if you close the mdi
> > window, and adds another button, it tracebacks with:
> >
> > Traceback (most recent call last):
> > File "dynresize.py", line 29, in addRow
> > if self.subwindow.isHidden():
> > RuntimeError: underlying C/C++ object has been deleted
>
> The docs say that a closed window will be hidden if you are passing
> your own QMdiSubWindow. It isn't really clear about what happens when
> you pass a QWidget. If you look at the C++ implementation of
> addSubWindow() you see that it is setting WA_DeleteOnClose in this
> case. So I think the current behaviour is correct.
Ah, I see, thanks.
For the sake of completeness, here's the fixed example, taking this
insight into account. It needs an extra show() on the subwindow widget
(iow the frame) to operate properly. Hrmpf. The trolls seem to play
games with the subwindow widget state. Searching for isWidgetHiddenByUs
in qmdisubwindow.cpp is quite informative in this regard. Oh, well..
Not your concern at least.
#!/usr/bin/env python
from PyQt4.QtCore import Qt, QTimer
from PyQt4.QtGui import *
import os, sys
class Window(QWidget):
def __init__(self):
QWidget.__init__(self)
self._buttonNr = 1
self.mdi = QMdiArea()
frame = QFrame()
frameLayout = QVBoxLayout(frame)
self.subwindow = QMdiSubWindow()
self.subwindow.setWidget(frame)
self.mdi.addSubWindow(self.subwindow)
button = QPushButton("Add button")
button.clicked.connect(self.addRow)
layout = QVBoxLayout(self)
layout.addWidget(self.mdi)
layout.addWidget(button)
def addRow(self):
if self.mdi.activeSubWindow() is None:
self.subwindow.show()
self.subwindow.widget().show()
button = QPushButton("Remove button %i" % self._buttonNr)
button.clicked.connect(self.delRow)
self._buttonNr += 1
self.subwindow.widget().layout().addWidget(button)
QTimer.singleShot(0, self.subwindow.adjustSize)
def delRow(self):
button = self.sender()
button.hide()
self.subwindow.widget().layout().removeWidget(button)
button.deleteLater()
QTimer.singleShot(0, self.subwindow.adjustSize)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
Thanks,
Pete
More information about the PyQt
mailing list