Signals and Missing Positional Arguments

后端 未结 2 1125
一向
一向 2020-12-12 03:48

I developed two windows in QtDesigner (SourceForm, DestinationForm) and used pyuic5 to convert their .ui pages. I am using a third class WController as a way to

2条回答
  •  渐次进展
    2020-12-12 04:17

    There's already an accepted answer to this question but I'll give mine anyway.

    The problematic slot is connected to the itemChanged(QTreeWidgetItem *item, int column) signal, so the pyqtSlot should look like @pyqtSlot(QTreeWidgetItem, int).

    Now, as ekhumoro pointed out, PyQt accepts to connect a signal to any Python callable, be it a method, a lambda, or an functor having a __call__ method. But it's less safe to do so rather than use @pyqtSlot.

    For example, Qt automatically disconnects when either the source QObject (who would emit the signal) is destroyed, or the target QObject (who has the Qt slot) is destroyed. For example, if you remove a widget, it's not necessary to signal to it that something happened elsewhere. If you use @pyqtSlot, a real Qt slot is created in your class, so this disconnection mechanism can apply. Also, Qt doesn't hold a strong reference to the target QObject, so it can be deleted.

    If you use any callable, for example a non-decorated, bound method, Qt will have no way to identify the target QObject of the connection. Worse, since you pass a Python callable, it will hold a strong reference to it, and the callable (the bound method) will in turn hold a reference to the final QObject, so your target QObject will not be garbage collected, until you manually disconnect it, or remove the source QObject.

    See this code, you can enable one connection or the other, and observe the difference in behavior, which shows whether the window can be garbage-collected or not:

    from PyQt5.QtWidgets import QApplication, QMainWindow
    
    app = QApplication([])
    
    def create_win():
        win = QMainWindow()
        win.show()
    
        # case 1
        # app.aboutToQuit.connect(win.repaint)  # this is a qt slot, so win can be deleted
    
        # case 2
        # app.aboutToQuit.connect(win.size)  # this is not a qt slot, so win can't be deleted
    
        # win should get garbage-collected here
    
    create_win()
    
    app.exec_()
    

提交回复
热议问题