从外部脚本更新进度条

时间:2018-11-21 03:29:47

标签: python multithreading pyqt progress-bar

我正在尝试从外部python脚本实时更新PyQt4进度条,因为该外部脚本会通过其循环运行。到目前为止,我已经提供了一个最小的,可行的工作示例;谁能指导我有关未来的最佳做法?

GUI.py:

import sys, os
from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'
from traits.api import HasTraits,Instance,on_trait_change,Int
from traitsui.api import View,Item,VGroup
import external
#from PyQt4.QtCore import QThread


class P1(QtGui.QWidget):
    def __init__(self, parent=None):
        super(P1, self).__init__(parent)
        layout = QtGui.QGridLayout(self)

        def setProgress():
            if P1.progress.value() == 0:
                self.button.setDisabled(True)
                self.button.setText('Computing Data')

            external.op()

            if P1.progress.value() == 100:
                self.button_dist.setText('Data Complete')

        self.button = QtGui.QPushButton('Compute Data', self)
        self.connect(self.button, QtCore.SIGNAL('clicked()'), setProgress)
        layout.addWidget(self.button, 1, 2, 1, 1)
        self.button.setDisabled(False)
        self.button.show()

        P1.progress = QtGui.QProgressBar(self)
        P1.progress.setMinimum = 0
        P1.progress.setMaximum = 100
        P1.progress.setValue(0)        
        layout.addWidget(P1.progress, 1, 3, 1, 3)
        P1.progress.show()

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.window = P1(self) 
        self.setCentralWidget(self.window)
        self.show()

if __name__ == '__main__':
    app = QtGui.QApplication.instance()
    w = MainWindow()
    sys.exit(app.exec_())

external.py:

import sys, os, time
from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'
from GUI import P1
#from PyQt4.QtCore import QThread


def op():
    for i in range(1, 101):
        p1 = P1()
        p1.progress.setValue(i)
        time.sleep(0.01)
        print(i)

为使此示例按我的预期工作,当您单击按钮Compute Data时,进度栏的填充速度应与在终端机上打印i in range(1,101)的速度相同。

1 个答案:

答案 0 :(得分:1)

由于GUI导入到GUI的外部和外部,因此您有一个循环导入会导致无限循环,这是设计不良的征兆。另一方面,进度条必须是该类的成员。另外,外部任务必须在线程中执行,并且要更新它们,您必须使用将数据传输到GUI线程的信号。

external.py

import sys, os, time
from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'

def op(progress):
    for i in range(1, 101):
        progress.emit(i)
        time.sleep(0.01)
        print(i)

GUI.py

import sys, os
from pyface.qt import QtGui, QtCore
os.environ['ETS_TOOLKIT'] = 'qt4'
import threading
# from traits.api import HasTraits,Instance,on_trait_change,Int
# from traitsui.api import View,Item,VGroup
import external


class P1(QtGui.QWidget):
    progressChanged = QtCore.Signal(int)

    def __init__(self, parent=None):
        super(P1, self).__init__(parent)
        self.button = QtGui.QPushButton('Compute Data')
        self.button.clicked.connect(self.start_task)
        self.progress = QtGui.QProgressBar(minimum=0, maximum=100, value=0)
        self.progressChanged.connect(self.on_progressChanged) 

        layout = QtGui.QGridLayout(self)
        layout.addWidget(self.button, 1, 2, 1, 1)    
        layout.addWidget(self.progress, 1, 3, 1, 3)

    @QtCore.Slot()
    def start_task(self):
        t = threading.Thread(target=external.op, args=(self.progressChanged, ), daemon=True)
        t.start()

    @QtCore.Slot(int)
    def on_progressChanged(self, val):
        self.progress.setValue(val)
        if val == self.progress.maximum():
            self.button.setDisabled(False)
            self.button.setText('Data Complete')
        else:
            self.button.setText('Computing Data')
            self.button.setDisabled(True)

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.window = P1() 
        self.setCentralWidget(self.window)
        self.show()

if __name__ == '__main__':
    app = QtGui.QApplication.instance()
    if app is None:
        app = QtGui.QApplication([])
    w = MainWindow()
    sys.exit(app.exec_())