当我们编写Python及PySide框架的GUI程序时,常常需要QFileSystemWatcher来监控特定文件。当文件发生变化时,QFileSystemWatcher会调用一个方法,该方法进而调用PySide类中的另一个方法。然而,我们也许会发现,PySide类方法中描述的GUI操作并未按预期执行。
举个例子:
# 定义PySide GUI类
class GUI(QMainWindow, Ui_GUI):
def __init__(self, parent=None):
super(GUI, self).__init__(parent)
self.setupUi(self)
# 按钮点击后,调用Run方法
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")
# 在PySide类外,建立文件监控机制
def FileChanged():
# 创建脚本对象
Script = GUI()
# 调用脚本对象的Run方法
Script.Run()
# 监控文件路径
Paths = ['path/to/file']
Watch = QtCore.QFileSystemWatcher(Paths)
# 当文件发生变化时,调用FileChanged方法
Watch.fileChanged.connect(FileChanged)
# 设置GUI
if __name__ == '__main__':
# 创建应用程序实例
app = QApplication(sys.argv)
# 实例化脚本对象
showGUI = GUI()
# 展示脚本对象
showGUI.show()
# 执行应用程序
app.exec_()
上述代码并不会产生任何错误,当被监控的文件发生变化时,FileChanged方法会正确调用GUI类的Run方法。然而,Run方法并不会按预期执行任何任务,只会输出预设的信息。如果我们点击GUI中的“按钮”,Run方法则可以正常执行并完成所有指定的任务。因此,我们的问题是,为什么Run方法不能正确执行任务?
2. 解决方案
在FileChanged方法中创建的Script对象是局部变量,当FileChanged方法返回时,Script对象会被垃圾回收。当信号触发时,如果调用Run槽,槽将会正确执行所有更改,但你无法看到这些更改,因为Script对象在它被展示之前就被删除了。为了使示例脚本开始任何操作,需要将代码重新排列如下:
# 设置GUI
if __name__ == '__main__':
# 创建应用程序实例
app = QtGui.QApplication(sys.argv)
# 实例化脚本对象
showGUI = GUI()
# 在PySide类外,建立文件监控机制
def FileChanged():
# 调用脚本对象的Run方法
showGUI.Run()
# 监控文件路径
Paths = ['path/to/file']
Watch = QtCore.QFileSystemWatcher(Paths)
# 当文件发生变化时,调用FileChanged方法
Watch.fileChanged.connect(FileChanged)
# 展示脚本对象
showGUI.show()
# 执行应用程序
app.exec_()
当然,实际的代码可能与示例中的代码有很大不同(示例中还存在许多其他阻止代码运行的错误),所以这个解决方案可能没有帮助。如果实际代码不同,需要发布一个完整的、自包含的示例,以便更好地演示遇到的问题。