PyQt4 работает правильно

Я хочу сделать прогрессбар, который работает в потоке, и я хочу иметь возможность перемещать виджет во время процесса:

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

Пока это работает, но очень плохо. Виджет практически не работает на моей машине, когда я пытаюсь переместить его во время процесса. Есть ли способ сделать эту работу лучше, чтобы виджет не отставал и не переставал отвечать?

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_())
Другие вопросы по тегам