带线程的 PyQt 进度条更新

     2023-03-25     237

关键词:

【中文标题】带线程的 PyQt 进度条更新【英文标题】:PyQt Progress Bar Update with Threads 【发布时间】:2017-08-04 18:44:49 【问题描述】:

我一直在编写一个在服务器上运行远程脚本的程序。所以,我需要用一个栏显示进度,但是当我运行我的代码时,GUI 开始冻结。我使用过 QThread 和 SIGNAL 但很遗憾无法成功。

下面是我的代码;

class dumpThread(QThread):

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()

    def sendEstablismentCommands(self, connection):

        # Commands are sending sequently with proper delay-timers #

        connection.sendShell("telnet localhost 21000")
        time.sleep(0.5)
        connection.sendShell("admin")
        time.sleep(0.5)
        connection.sendShell("admin")
        time.sleep(0.5)
        connection.sendShell("cd imdb")
        time.sleep(0.5)
        connection.sendShell("dump subscriber")

        command = input('$ ')

    def run(self):
        # your logic here              
        # self.emit(QtCore.SIGNAL('THREAD_VALUE'), maxVal)
        self.sendEstablismentCommands(connection)    

class progressThread(QThread):

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()


    def run(self):
        # your logic here
        while 1:      
            maxVal = 100
            self.emit(SIGNAL('PROGRESS'), maxVal)

class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.connectButton.clicked.connect(self.connectToSESM)



    def connectToSESM(self):
        ## Function called when pressing connect button, input are being taken from edit boxes. ##
        ## dumpThread() method has been designed for working thread seperate from GUI. ##

        # Connection data are taken from "Edit Boxes"
        # username has been set as hardcoded

        ### Values Should Be Defined As Global ###
        username = "ntappadm"
        password = self.ui.passwordEdit.text()
        ipAddress = self.ui.ipEdit.text()

        # Connection has been established through paramiko shell library
        global connection

        connection = pr.ssh(ipAddress, username, password)
        connection.openShell()
        pyqtRemoveInputHook()  # For remove unnecessary items from console

        global get_thread

        get_thread = dumpThread() # Run thread - Dump Subscriber
        self.progress_thread = progressThread()

        self.progress_thread.start()
        self.connect(self.progress_thread, SIGNAL('PROGRESS'), self.updateProgressBar)

        get_thread.start()     




    def updateProgressBar(self, maxVal):

        for i in range(maxVal):
            self.ui.progressBar.setValue(self.ui.progressBar.value() + 1)
            time.sleep(1)
            maxVal = maxVal - 1

            if maxVal == 0:
                self.ui.progressBar.setValue(100)

    def parseSubscriberList(self):
        parsing = reParser()

    def done(self):
        QtGui.QMessageBox.information(self, "Done!", "Done fetching posts!")




if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    main = Main()
    main.show()
    sys.exit(app.exec_())

我希望看到 updateProgressBar 方法已通过 SIGNAL 调用,因此进程通过单独的线程。我找不到我失踪的地方。

感谢您的帮助

【问题讨论】:

如何在信号中定义整数?你能详细说明一下:progress_update = QtCore.Signal(int) 吗? 1. progressThread 的目的是什么?您有一个工作线程并且想要相应地更新您的 GUI,所以我看不到第三个线程的必要性。 2.为什么updateProgressBar中有一个循环?为什么每次迭代都减少maxVal?为什么你有一个time.sleep 在那里?当然,如果你让它休眠,你的主线程会冻结。此外,每次调用updateProgressBar 最终都会执行self.ui.progressBar.setValue(100),因为maxVal 在最后一次迭代中为零。 【参考方案1】:

确实有两个问题。我注意到的一件事是,如果 Python 线程不用于 IO 操作(例如从串行端口读取),则它们是贪婪的。如果您告诉线程运行计算或与 IO 无关的东西,线程将占用所有处理并且不喜欢让主线程/事件循环运行。第二个问题是信号很慢……非常慢。我注意到如果你从一个线程发出一个信号并且非常快地执行它会大大减慢程序的速度。

所以问题的核心是,线程一直在占用所有时间,而您发出的信号非常非常快,这将导致速度变慢。

为了清晰和易于使用,我将使用新样式的信号和插槽。 http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html

class progressThread(QThread):

    progress_update = QtCore.Signal(int) # or pyqtSignal(int)

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()


    def run(self):
        # your logic here
        while 1:      
            maxVal = 100
            self.progress_update.emit(maxVal) # self.emit(SIGNAL('PROGRESS'), maxVal)
            # Tell the thread to sleep for 1 second and let other things run
            time.sleep(1)

连接到新风格的信号

...
self.progress_thread.start()
self.process_thread.progress_update.connect(self.updateProgressBar) # self.connect(self.progress_thread, SIGNAL('PROGRESS'), self.updateProgressBar)
...

编辑 抱歉还有一个问题。当一个信号调用一个函数时,你不能永远留在那个函数中。该函数没有在单独的线程中运行,而是在主事件循环上运行,并且主事件循环等待运行,直到您退出该函数。

更新进度休眠 1 秒并不断循环。悬念来自于停留在这个函数中。

def updateProgressBar(self, maxVal):

    for i in range(maxVal):
        self.ui.progressBar.setValue(self.ui.progressBar.value() + 1)
        time.sleep(1)
        maxVal = maxVal - 1

        if maxVal == 0:
            self.ui.progressBar.setValue(100)

进度条最好写成这样

class progressThread(QThread):

    progress_update = QtCore.Signal(int) # or pyqtSignal(int)

    def __init__(self):
        QThread.__init__(self)

    def __del__(self):
        self.wait()


    def run(self):
        # your logic here
        while 1:      
            maxVal = 1 # NOTE THIS CHANGED to 1 since updateProgressBar was updating the value by 1 every time
            self.progress_update.emit(maxVal) # self.emit(SIGNAL('PROGRESS'), maxVal)
            # Tell the thread to sleep for 1 second and let other things run
            time.sleep(1)


def updateProgressBar(self, maxVal):
    self.ui.progressBar.setValue(self.ui.progressBar.value() + maxVal)
    if maxVal == 0:
        self.ui.progressBar.setValue(100)

【讨论】:

感谢您的回答,但我的 Gui 仍然冻结。看起来没什么变化。顺便说一句,我使用了 pyqtSignal(int) 我编辑了答案并添加了有关在 updateProgressBar 中停留时间过长的信息。 是的,你是对的,代码正在等待结束progressBarUpdate中的for循环。我已经更新现在它正在工作。谢谢大家

pyqt使用线程更新进度条

】pyqt使用线程更新进度条【英文标题】:pyqtupdatingprogressbarusingthread【发布时间】:2019-12-1217:32:25【问题描述】:我想使用线程方法从我的main.py更新进度条。if__name__=="__main__":app=QApplication(sys.argv)uiplot=gui.Ui_MainWindow()Update_Progressbar... 查看详情

pyqt5进度条qprogressbar的使用/多线程更新/按钮美化/图片编码/开机自启动(代码片段)

前言诚如标题所见,我在使用Pyqt5进行开发时,先后遇到了上面几个问题。本篇博客就用来记录遇到问题/解决问题的过程,希望能给遇到相同问题的读者一些参考。项目背景我的项目是构建一个可视化的交互界面࿰... 查看详情

如何在 Ui_MainWindow 中更新 pyqt5 进度条

...,目前在线文档似乎非常有限。我在网上读到我可以使用线程和信号来做到这一点。但是,pyqt5中的语法似乎发生了变化。这里有专家可以帮忙吗?主界面窗口。#-*-coding:utf-8 查看详情

根据从导入包中打印的标准输出更新 PyQt 进度条(PyQt5)

】根据从导入包中打印的标准输出更新PyQt进度条(PyQt5)【英文标题】:UpdatingPyQtprogressbarbasedonprintedstdoutfromimportedpackage(PyQt5)【发布时间】:2017-05-2005:57:43【问题描述】:我对PyQt5比较陌生,希望能获得任何指导以实现以下目标... 查看详情

pyqt 是不是支持具有两个值的堆叠进度条?

...于thisquestion,但用于pyqt。我有一个应用程序,它有两个线程,其中一个处理一些数据(耗时),第二个线程显示结果并要求对结果进行验证。我想在进度条中显示处理的对象数量 查看详情

PyQt:如何在不冻结 GUI 的情况下更新进度?

...2010-10-0820:27:03【问题描述】:问题:什么是最佳实践跟踪线程的在不锁定GUI的情况下进行(“没有回应”)?一般来说,最佳实践是什么?线程,因为它适用于GUI开发?问题背景:我有一个适用于Windows的PyQtGUI。用于处理HTML集文... 查看详情

带有进度条更新的 C++ 多线程套接字操作

】带有进度条更新的C++多线程套接字操作【英文标题】:C++Multithreadedsocketoperationwithprogressbarupdate【发布时间】:2014-06-1221:34:20【问题描述】:我有一个正在实现的MFCDLL。主线程创建一个进度条(CProgressCtrl),然后启动一个CWinThr... 查看详情

android中progressdialog进度条对话框的使用(使用子线程模拟更新进度)

​前言:使用ProgressDialog可以实现多种样式,今天我们就来实现模拟水平进度条更新的效果。具体实现:布局页面一个按钮就不再说明。下面来看在Activity代码中的实现:publicclassMainActivityextendsAppCompatActivityimplementsView.OnClickListener... 查看详情

MVC 进度条线程

】MVC进度条线程【英文标题】:MVCProgressBarThreading【发布时间】:2011-07-2820:34:03【问题描述】:我在我的设计中使用MVC模式,当用户按下搜索按钮时,我会在模型中调用搜索,但我还想使用从该模型返回的信息更新进度条。我尝... 查看详情

android中progressdialog进度条对话框的使用(使用子线程模拟更新进度)(代码片段)

前言:使用ProgressDialog可以实现多种样式,今天我们就来实现模拟水平进度条更新的效果。具体实现:布局页面一个按钮就不再说明。下面来看在Activity代码中的实现:publicclassMainActivityextendsAppCompatActivityimplementsVie... 查看详情

多线程任务更新 1 个进度条 - UI C# WPF

】多线程任务更新1个进度条-UIC#WPF【英文标题】:Multiplethreadstasksupdating1progressbar-UIC#WPF【发布时间】:2021-07-1619:30:51【问题描述】:我一直在四处寻找有类似问题的人,但没有找到任何东西。我正在使用WPFUI编写C#应用程序。要... 查看详情

如何在 UI 线程中工作时更新进度条

】如何在UI线程中工作时更新进度条【英文标题】:HowtoupdateprogressbarwhileworkingintheUIthread【发布时间】:2015-09-0311:50:30【问题描述】:我有一个ProgressBar和一个TreeView。我用一堆数据填充了TreeView,一旦应用它,我运行TreeView的visual... 查看详情

wpf多线程进度条更新进度(代码片段)

主要的使用类:DispatcherusingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Data;usingSystem.Windows.Documents;usingSystem.Windows.Input;usingSystem.Windows.Media;us... 查看详情

pyqt5之进度条:qprogressbar(代码片段)

PyQt5之进度条:QProgressBar在软件中,在处理特别冗长的任务时,如果没有相关的进度信息,这个等待的过程会比较考验用户的耐心,根据相关理论,进度条可以缓解用户在等待过程中的焦虑,所以,... 查看详情

如何制作不从零开始的 PyQt 进度条

【中文标题】如何制作不从零开始的PyQt进度条【英文标题】:HowtomakeaPyQtProgressBarthatdoesn\'tstartfromzero【发布时间】:2018-03-0818:00:03【问题描述】:它总是从零开始,但我想做一个加载栏Justlikethisone【问题讨论】:【参考方案1】... 查看详情

更新原始活动中的集成进度条

...的文件扫描器应用程序中工作,但我完全被活动、服务、线程和处理程序的正确组合所困扰。结构如下:我的Activity包含一个水平样式的ProgressBar。单击菜单项时,我会生成一个Service,它是onCrea 查看详情

Python 3.5,单独窗口中的 pyqt5 进度条 gui

】Python3.5,单独窗口中的pyqt5进度条gui【英文标题】:Python3.5,pyqt5progressbarguiinseperatewindow【发布时间】:2016-11-0423:23:09【问题描述】:我是PyQt5的新手,对Python还是很陌生。我正在尝试在Python3.5中使用PyQt5创建一个图形用户界面,... 查看详情

达到/设置某个值后如何重置 PYQT5 进度条?

】达到/设置某个值后如何重置PYQT5进度条?【英文标题】:HowtoresetaPYQT5progressbaronceacertainvaluehasbeenreached/set?【发布时间】:2020-07-2014:14:35【问题描述】:我目前正在创建将一些数据分析脚本联系在一起的基本GUI。这些脚本可能需... 查看详情