PyQt4 线程正确
PyQt4 threading properly
我想制作一个 运行 在线程上的进度条,并且我希望能够在此过程中移动小部件:
import sys
from PyQt4.QtGui import QApplication, QMainWindow, QPushButton, QLineEdit, QLabel, QComboBox, QProgressBar, QFileDialog
from PyQt4.QtCore import QSize, pyqtSlot, QCoreApplication, SIGNAL, QThread
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.setGeometry(500, 300, 820, 350)
self.setWindowTitle("Program")
self.initUI()
def initUI(self):
#Buttons
btnposx = 30
btnposy = 50
self.btn4 = QPushButton('Load', self)
self.btn4.move(btnposx,btnposy+220)
self.connect(self.btn4, SIGNAL("released()"), self.test)
#ProgressBar
self.pb = QProgressBar(self)
self.pb.move(btnposx+150,btnposy+220)
self.pb.resize(470,27)
self.show()
def load(self, val):
self.pb.setValue(val)
def test(self):
self.workThread = WorkThread()
self.connect( self.workThread, SIGNAL('pb_update'), self.load)
self.workThread.start()
class WorkThread(QThread):
def __init__(self):
super(WorkThread, self).__init__()
QThread.__init__(self)
def __del__(self):
self.wait()
@pyqtSlot()
def run(self):
val = 0
l = range(1000000)
for i in l:
if i < len(l):
val += 100/len(l)
self.emit(SIGNAL('pb_update'), val)
return
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
到目前为止这可行,但效果很差。当我尝试在此过程中移动它时,Widget 在我的机器上几乎没有 运行。有没有办法让这项工作变得更好,这样 Widget 就不会滞后或停止响应?
您的代码可以进行的改进如下:
- 在信号和槽之间使用新的连接方式
- 您必须留出一点时间让副线程将信息发送给主线程。
- 您必须指明连接类型,在您的情况下
Qt::QueuedConnection
。
- 使用
pyqtSlot
装饰器。
- 你只需要在必要时发出信号,在你的情况下,由于
QProgressBar
不识别浮动,所以值的整个值发生变化。
import sys
from PyQt4.QtGui import QApplication, QMainWindow, QPushButton, QLineEdit, QLabel, QComboBox, QProgressBar, QFileDialog
from PyQt4.QtCore import QSize, pyqtSlot, pyqtSignal, QThread, Qt
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.setGeometry(500, 300, 820, 350)
self.setWindowTitle("Program")
self.initUI()
def initUI(self):
#Buttons
btnposx = 30
btnposy = 50
self.btn4 = QPushButton('Load', self)
self.btn4.move(btnposx,btnposy+220)
self.btn4.released.connect(self.test)
#ProgressBar
self.pb = QProgressBar(self)
self.pb.move(btnposx+150,btnposy+220)
self.pb.resize(470,27)
self.show()
@pyqtSlot(int)
def load(self, val):
self.pb.setValue(val)
def test(self):
self.workThread = WorkThread()
self.workThread.pb_update.connect(self.load, Qt.QueuedConnection)
#self.workThread.pb_update.connect(self.pb.setValue)
self.workThread.start()
class WorkThread(QThread):
pb_update = pyqtSignal(float)
def __init__(self, *args, **kwargs):
QThread.__init__(self, *args, **kwargs)
self.value = 0
def __del__(self):
self.wait()
@pyqtSlot()
def run(self):
val = 0
l = range(1000000)
for i in l:
if i < len(l):
val += 100/len(l)
int_val = int(val)
if int_val != self.value:
self.value = int_val
self.pb_update.emit(self.value)
QThread.msleep(1)
return
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
我想制作一个 运行 在线程上的进度条,并且我希望能够在此过程中移动小部件:
import sys
from PyQt4.QtGui import QApplication, QMainWindow, QPushButton, QLineEdit, QLabel, QComboBox, QProgressBar, QFileDialog
from PyQt4.QtCore import QSize, pyqtSlot, QCoreApplication, SIGNAL, QThread
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.setGeometry(500, 300, 820, 350)
self.setWindowTitle("Program")
self.initUI()
def initUI(self):
#Buttons
btnposx = 30
btnposy = 50
self.btn4 = QPushButton('Load', self)
self.btn4.move(btnposx,btnposy+220)
self.connect(self.btn4, SIGNAL("released()"), self.test)
#ProgressBar
self.pb = QProgressBar(self)
self.pb.move(btnposx+150,btnposy+220)
self.pb.resize(470,27)
self.show()
def load(self, val):
self.pb.setValue(val)
def test(self):
self.workThread = WorkThread()
self.connect( self.workThread, SIGNAL('pb_update'), self.load)
self.workThread.start()
class WorkThread(QThread):
def __init__(self):
super(WorkThread, self).__init__()
QThread.__init__(self)
def __del__(self):
self.wait()
@pyqtSlot()
def run(self):
val = 0
l = range(1000000)
for i in l:
if i < len(l):
val += 100/len(l)
self.emit(SIGNAL('pb_update'), val)
return
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
到目前为止这可行,但效果很差。当我尝试在此过程中移动它时,Widget 在我的机器上几乎没有 运行。有没有办法让这项工作变得更好,这样 Widget 就不会滞后或停止响应?
您的代码可以进行的改进如下:
- 在信号和槽之间使用新的连接方式
- 您必须留出一点时间让副线程将信息发送给主线程。
- 您必须指明连接类型,在您的情况下
Qt::QueuedConnection
。 - 使用
pyqtSlot
装饰器。 - 你只需要在必要时发出信号,在你的情况下,由于
QProgressBar
不识别浮动,所以值的整个值发生变化。
import sys
from PyQt4.QtGui import QApplication, QMainWindow, QPushButton, QLineEdit, QLabel, QComboBox, QProgressBar, QFileDialog
from PyQt4.QtCore import QSize, pyqtSlot, pyqtSignal, QThread, Qt
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.setGeometry(500, 300, 820, 350)
self.setWindowTitle("Program")
self.initUI()
def initUI(self):
#Buttons
btnposx = 30
btnposy = 50
self.btn4 = QPushButton('Load', self)
self.btn4.move(btnposx,btnposy+220)
self.btn4.released.connect(self.test)
#ProgressBar
self.pb = QProgressBar(self)
self.pb.move(btnposx+150,btnposy+220)
self.pb.resize(470,27)
self.show()
@pyqtSlot(int)
def load(self, val):
self.pb.setValue(val)
def test(self):
self.workThread = WorkThread()
self.workThread.pb_update.connect(self.load, Qt.QueuedConnection)
#self.workThread.pb_update.connect(self.pb.setValue)
self.workThread.start()
class WorkThread(QThread):
pb_update = pyqtSignal(float)
def __init__(self, *args, **kwargs):
QThread.__init__(self, *args, **kwargs)
self.value = 0
def __del__(self):
self.wait()
@pyqtSlot()
def run(self):
val = 0
l = range(1000000)
for i in l:
if i < len(l):
val += 100/len(l)
int_val = int(val)
if int_val != self.value:
self.value = int_val
self.pb_update.emit(self.value)
QThread.msleep(1)
return
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())