Search code examples
pythonpysideqfilesystemwatcher

Calling a class method in Python/PySide


I spent longer than I'd care to admit think of a suitable 'question' heading for this topic, as my issue is somewhat hard to articulate.

Here is a quick summary of the situation:

  • I'm writing a basic GUI with Python 3.4 and PySide
  • I'm using QFileSystemWatcher to monitor a particular file
  • When the file is changed, QFileSystemWatcher calls a method, which in turn calls a method within a PySide Class
  • All of the above seems to be working perfectly, except the GUI-specific actions detailed in the PySide Class method aren't being executed (I'll explain in more detail below).

Example code:

#Establishing the PySide GUI Class
class GUI(QMainWindow, Ui_GUI):
    def __init__(self, parent=None)
        super(GUI, self).__init__(parent)
        self.setupUi(self)

        QtCore.QObject.connect(self.Button, QtCore.SIGNAL("clicked()"), self.Run)

    def Run(self):
        print("1")

        self.treeWidget1.clear()
        self.treeWidget2.clear()

        print("2")

        self.label1.setText("Text 1")
        self.label2.setText("Text 2")

        print("3")

        for y in range(0, 5):
            self.treeWidget1.resizeColumnsToContents()

        print("Finished")

#Establish the file monitoring mechanism, *outside* the PySide class
def FileChanged():
    Script = GUI()
    Script.Run()

Paths = ['path/to/file']
Watch = QtCore.QFileSystemWatcher(Paths)
Watch.fileChanged.connect(FileChanged)

#Setting up the GUI
if __name__ == '__main__':
    app = QApplication(sys.argv)
    showGUI = GUI()
    showGUI.show()
    app.exec_()

As I mentioned above, the above code doesn't return any errors. When I change the file (listed in the path), FileChanged does indeed call the Run() method from the GUI class. However, it won't actually do any of the 'stuff', it will only execute the print commands in between the 'stuff'.

If I then click on the 'Button' in the GUI, it will execute Run() correctly, and properly execute all the 'stuff'.

My question: is there something I'm missing here? If it's calling the method correctly, and is able to execute the various 'print' commands, why is it not executing the actual 'stuff'?

Thanks!

EDIT 1: I've removed the -do stuff- tags and put in some example code. All the 'stuff' code relates to updating various PySide QLabels, QTreeWidgets, etc.

EDIT 2: I forget the () at the end of the treeWidget clear commands.


Solution

  • The Script object created in the FileChanged function has local scope, and will be garbage-collected as soon as the function returns.

    If the Run slot gets called when the signal fires, it will carry out all of the changes correctly, but you won't get to see any of those changes, because Script will be deleted before it is ever shown.

    In order to for the example script to begin to make any sense, it would need to be re-arranged to something like this:

    #Setting up the GUI
    if __name__ == '__main__':
    
        app = QtGui.QApplication(sys.argv)
    
        showGUI = GUI()
    
        #Establish the file monitoring mechanism, *outside* the PySide class
        def FileChanged():
            showGUI.Run()
    
        Paths = ['path/to/file']
        Watch = QtCore.QFileSystemWatcher(Paths)
        Watch.fileChanged.connect(FileChanged)
    
        showGUI.show()
    
        app.exec_()
    

    Of course, it's possible that your real code is nothing like the example in your question (which has numerous other errors preventing it from being run), and so this might be no help. But if that is the case, you will have to post a fully working, self-contained example that properly demonstrates the problems you are having.