【问题标题】:PyQt4 threading properlyPyQt4线程正确
【发布时间】:2018-10-04 15:33:23
【问题描述】:

我想制作一个在线程上运行的进度条,并且我希望能够在此过程中移动小部件:

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 就不会滞后或停止响应?

【问题讨论】:

    标签: python pyqt pyqt4 qthread qprogressbar


    【解决方案1】:

    您的代码可以进行的改进如下:

    • 在信号和插槽之间使用新的连接方式
    • 您必须留一点时间让辅助线程将信息发送到主线程。
    • 您必须指明连接类型,在您的情况下为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_())
    

    【讨论】:

    • 非常感谢您的回答。我试过你的代码,但它似乎不起作用。没有错误,ProgressBar 只是不会开始加载。它保持在 0%
    • 完美流畅!非常感谢:-)
    猜你喜欢
    • 2015-10-27
    • 2011-07-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    相关资源
    最近更新 更多