【问题标题】:Updating progress bar from external script从外部脚本更新进度条
【发布时间】:2018-11-21 03:29:47
【问题描述】:

我正在尝试从外部 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) 的速度相同。

【问题讨论】:

  • 外部脚本通常是指单独的程序作为单独的进程运行。但是您只想从在同一进程中运行的其他模块访问进度条,不是吗?
  • @KlausD。好吧,我实际上不确定。这是一个帮助我解决实际问题的示例,其中 GUI 调用另一个脚本,然后随着外部脚本循环更新 GUI 的进度条。
  • 对于您的“真正问题”,您可以导入其他脚本,当您运行函数或从中运行任何内容时,将带有进度条的 GUI 对象的引用作为参数传递给它。那么其他脚本中的代码就可以直接更新了。

标签: python multithreading pyqt progress-bar


【解决方案1】:

您有一个循环导入,导致无限循环,因为 GUI 导入到 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_())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    相关资源
    最近更新 更多