Search code examples
pythonqtpyqtqt5qwidget

Move QWidget from one window to another (in PyQt)


The idea is, to pop a QWidget into its own QMainWindow. Beforehand it's the central widget of window A, and afterwards A should have a filler widget, a new window B is spawned with the widget as its own central widget.

So here's the setup:

class DetachedWindow(QtWidgets.QMainWindow):
    def __init__(self, window: "MyMainWindow", widget: QtWidgets.QWidget = None, *args):
        QtWidgets.QMainWindow.__init__(self, *args)
        self.main_window = window
        window.set_widget(EmptyWidget(), False)  # sets new filler central widget
        if widget is not None:
            self.setCentralWidget(widget)
            widget.setParent(self)
        self.show()

class MyMainWindow(QtWidgets.QMainWindow):
    # ...
    def detach_screen(self):
        self.windows.append(DetachedWindow(self, self.current_widget))

But when I try it, the DetachedWindow is just empty. When I replace widget in setCentralWidget with the constructor of a QWidget, it is displayed correctly. But not with the adopted widget.

What am I missing here?

Update: Apparently the widget is deleted. When accessing the setText function of one of its labels, the following error occurs:

RuntimeError: wrapped C/C++ object of type QLabel has been deleted

Solution

  • I don't know why, but calling widget.show() afterwards solves the issue.

    class DetachedWindow(QtWidgets.QMainWindow):
        def __init__(self, window: "MyMainWindow", widget: QtWidgets.QWidget = None, *args):
            QtWidgets.QMainWindow.__init__(self, *args)
            self.main_window = window
            window.set_widget(EmptyWidget(), False)  # sets new filler central widget
            self.show()
            if widget is not None:
                self.setCentralWidget(widget)
                widget.setParent(self)
                widget.show()
    
    class MyMainWindow(QtWidgets.QMainWindow):
        # ...
        def detach_screen(self):
            self.windows.append(DetachedWindow(self, self.current_widget))
    

    Any explanation for this? It does not really seem like this works as intended...