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_())