PyQt4 работает правильно - PullRequest
0 голосов
/ 24 апреля 2018

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

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 Ответ

0 голосов
/ 24 апреля 2018

Улучшения, которые может иметь ваш код, следующие:

  • Использование нового стиля соединения между сигналами и слотами
  • Вы должны оставить немного времени для отправки вторичного потокаинформация для основного потока.
  • Вы должны указать тип соединения, в вашем случае 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_())
...