Widget's “destroyed” signal is not fired (PyQT)

前端 未结 2 726
Happy的楠姐
Happy的楠姐 2021-01-17 23:26

I have a widget which would have to do some manual cleanup after it\'s destroyed (stop some threads). However for some reason the \"destroyed\" signal of the widget is not f

相关标签:
2条回答
  • 2021-01-17 23:59

    The python class instance (or at least the pyqt<->qt link) doesn't exist by the time destroyed is emitted. You can work around this by making the destroyed handler a staticmethod on the class. This way, the python method will still exist when the destroyed signal is emitted.

    class MyWidget(QWidget):
    
        def __init__(self, parent):
            super(MyWidget, self).__init__(parent)
            self.destroyed.connect(MyWidget._on_destroyed)
    
        @staticmethod
        def _on_destroyed():
            # Do stuff here
            pass
    

    If you need information specific to the class instance you can use functools.partial and the instance __dict__ to pass that info to the destruction method.

    from functools import partial
    
    class MyWidget(QWidget):
    
        def __init__(self, parent, arg1, arg2):
            super(MyWidget, self).__init__(parent)
            self.arg1 = arg1
            self.arg2 = arg2
            self.destroyed.connect(partial(MyWidget._on_destroyed, self.__dict__))
    
        @staticmethod
        def _on_destroyed(d):
            print d['arg1']
    
    0 讨论(0)
  • 2021-01-18 00:15

    After a few tries I found out that it works if you declare the doSomeDestruction outside the class. (see at the bottom)
    But I don't know why. As written in this answer, this is because At the point destroyed() is emitted, the widget isn't a QWidget anymore, just a QObject (as destroyed() is emitted from ~QObject).
    This means when your function would be called it is already deleted if you write it in the class. (look also here in the qt-interest mailing list: Ok , I am sorry for stupid question. The signal is emitted, but the slot is not called for the obvious reason, that is because object is already deleted. )

    EDIT: I've found two ways make it really work:

    1. add a simple del window after ret = app.exec_().
    2. Set the WA_DeleteOnClose attribute in the main window (not the widget):
      At the top of the program:

      from PyQt4 import QtCore
      

      The changed __init__ function:

      class MyWindow(QtGui.QMainWindow):
          def __init__(self):
              super(MyWindow, self).__init__()
              self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
              self.widget = MyWidget(self)
      
    0 讨论(0)
提交回复
热议问题