Wrecked signal widget not starting (PyQT)

I have a widget that would have to perform a manual cleanup after it was destroyed (stop some threads). However, for some reason, the "broken" widget signal does not work. I made this small example demonstrating the problem.

import sys from PyQt4 import QtGui class MyWidget(QtGui.QWidget): def __init__(self, parent): super(MyWidget, self).__init__(parent) def doSomeDestruction(): print('Hello World!') self.destroyed.connect(doSomeDestruction) class MyWindow(QtGui.QMainWindow): def __init__(self): super(MyWindow, self).__init__() self.widget = MyWidget(self) app = QtGui.QApplication(sys.argv) window = MyWindow() window.show() ret = app.exec_() sys.exit(ret) 

I expected him to print "Hello World!" when the main window is closed. However, it does not print anything.

+6
source share
2 answers

After several attempts, I found that it works if you declare doSomeDestruction outside the class. (see below)
But I do not know why. As written in this , 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 that when your function is called, it is already deleted if you write it in the class. (See qt-interest mailing list here : 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 found two ways to do this really:

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

     from PyQt4 import QtCore 

    Modified __init__ function:

     class MyWindow(QtGui.QMainWindow): def __init__(self): super(MyWindow, self).__init__() self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) self.widget = MyWidget(self) 
+5
source

An instance of the python class (or at least the pyqt ↔ qt reference) does not exist at the time the destroyed timeout expires. You can get around this by creating the destroyed handler of a staticmethod in the class. This way the python method will exist when the destroyed signal is issued.

 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 related to an instance of a class, you can use functools.partial and an __dict__ instance to pass this information to the kill 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
source

Source: https://habr.com/ru/post/946200/


All Articles