PYQT作为界面程序包,为Pythoner快速构建界面,提供了便利性。特别是结合Pycharm扩展工具(QTdesigner)能够通过“拖拖拽拽”的方式构建简单界面。通过UIC将UI文件快速转化为PY文件,节省了时间。
PYQT的项目实践,必须参照MVC模式,才能形成多人工作合力,关于MVC的实践,会另起它文进行总结归纳,本文重点总结归纳PYQT项目中,因耗时操作产生界面卡顿现象时,如何通过分线程的方式,解决主界面线程等待造成界面卡顿的问题。
一、问题的出现
设计了一个界面,去局域网共享文件夹中查看是否存在文件,若存在,则在textBrowser中显示文件数量,每隔几秒钟执行一次,同时将信息Append到textBrowser中。
使用os.listdir(target_path)打开共享文件夹时,由于网络故障,待反馈耗时大,由于Ui_MainWindow中的方法都在主线程中进行,造成界面的卡顿。
二、解决思路
将耗时操作分离至新线程,主界面保留资源用于交互。查询网络上现有的解决思路,大致如下:利用PYQT中的QThread类,新起一个线程,用来处理共享文件夹查阅的操作,待该线程处理完成后,主线程接收子线程处理结果,append到textBrowser中。
三、难点
利用信号与槽的机制,将主、子线程建立关联关系。
四、如何实现
1、实例化Ui_MainWindow类的MyThread对象,用于填装子线程处理任务。
self.my_thread = MyThread()
2、将事件信号与槽函数建立联系,通过count函数启用线程。
self.StopButton.clicked.connect(self.CountFilesNum)
3、Count函数:
self.textBrowser_2.append("开始检测……")
self.my_thread.is_on = True
self.my_thread.start()#启动线程
4、设计MyThread类,继承Qthread类
my_signal = pyqtSignal(str) #
tipwords = ''
def __init__(self):
super(MyThread, self).__init__()
self.tipwords = ''
self.is_on = True
定义一个信号(my_signal)用于向槽函数传递字符型变量(字符会输出到textBrowser中),调用父类的INIT方法,完成初始化设置。
5、定义线程中的主逻辑函数:
all_content = os.listdir(target_path)
……
self.my_signal.emit(str(self.tipwords))
函数执行完,释放信号。线程中的信号关联到append函数
self.my_thread.my_signal.connect(self.appendTextBrowser)
实现了线程中数据返回主线程的目的。
五、总结
除了button中的信号与槽机制外,主、子线程也是通过信号与槽机制完成的关联,可见,信号与槽机制,确实是PYQT的核心。
在使用pyqt开发界面时,遇到了一种情况,就是在点击按钮之后,响应函数中会启动一个循环,该循环会一直执行,然后就造成界面无响应,如下所示,由于我是在Linux下运行的,所以界面直接显示成灰色(windows应该显示“无响应”):
这是因为对于pyqt来说,界面线程是主线程,如果我们在主线程函数里面调用了一个耗时比较久的循环,可能就会造成主界面线程卡死在循环中,从而造成无法操作主界面或者主界面卡顿、卡死。
所以这种情况下必须使用多线程的方式来解决,即在主界面线程中在启动一个新的子线程,利用该子线程处理比较耗时的操作,然后通过signal-slot机制将子线程的数据反馈到主界面线

本文探讨了PyQt界面程序中遇到的界面卡顿问题及其解决办法。通过使用多线程技术,特别是QThread,可以有效避免长时间操作导致的界面无响应。介绍了两种常见多线程实现方式及信号与槽机制的应用。

1万+

被折叠的 条评论
为什么被折叠?



