使用python写程序,并用PyQt创建一个Gui。

问题描述

当python程序运行耗费时间过长时,便会阻塞Gui进程,导致Gui无法刷新,从而使得程序出现“未响应”的情况。

解决办法

这种情况下便需要使用Python的多线程功能。
最常见的线程协同方式:UI主线程+后台线程
UI被触发后,对应的主线程创建后台线程,后台线程在后台运行,并通过发信号给主线程,从而间接控制UI的显示。

例子

以下是我编写的一个英雄联盟语音汉化程序(因为在国外,LOL只能玩俄服,俄服的俄语虽然也好听,但终究感觉不如汉语亲切,于是便用python写了这个汉化小程序),程序功能极其简单,就是简单的把汉语语音解压到俄服LOL的安装文件夹语音文件位置,并将其覆盖。但是,解压很耗费时间,如果将解压程序和UI放在一个线程里,就会导致程序长时间的“未响应”状态,这就是因为解压过程阻塞了UI进程。后来使用多线程改进后问题得到解决。以下是部分程序(不完整,程序不太重要的部分被略去了)

hanhua.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from PyQt4 import QtCore, QtGui
import sys
import os

class Ui_Dialog(QtGui.QWidget):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.retranslateUi(self)
self.connect(self.pushButton, QtCore.SIGNAL('clicked()'),self.un_zip) //点击按钮后进入un_zip函数
self.setWindowIcon(QtGui.QIcon('web.png'))
self.setWindowTitle(_fromUtf8('LOL俄服汉化'))
def setupUi(self, Dialog):
... //初始化UI,程序略

def retranslateUi(self, Dialog):
Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
self.pushButton.setText(_translate("Dialog", "汉化", None))
self.label.setText(_translate("Dialog", "LOL俄服汉化语音", None))
self.label_2.setText(_translate("Dialog", "--By Root lee", None))
self.label_3.setText(_translate("Dialog", "适用于俄服5.16版", None))
def updateUI(self):
... //更新UI,程序略
def un_zip(self):
from threads import MyThread //导入进程类
self.bwThread = MyThread() //新建进程对象
self.connect(self.bwThread.QtCore.SIGNAL("where"),self.updateUI) //关联子进程发射过来的信号与updateUI函数
self.bwThread.start() //运行子线程

thread.py

1
2
3
4
5
6
7
8
9
10
from PyQt4 import QtCore, QtGui
import zipfile

class MyThread(QtCore.QThread):
def __init__(self,parent = None):
... //初始化,程序略
def run(self):
... //解压相关代码,略
self.emit(QtCore.SIGNAL("where"),j) //发送"where"信号给UI线程,然后UI线程调用updateUI()函数来更新UI