gpt4 book ai didi

Python pyqt 多线程脉冲进度条

转载 作者:行者123 更新时间:2023-12-01 02:47:01 24 4
gpt4 key购买 nike

请耐心解答我的问题,因为我是初学者。我在 pyqt 中实现进度条时遇到问题,我看到的所有示例都没有真正解释如何正确实现它,并且从这个 example还有这个example我在某种程度上使其工作正常,但它仍然挂起。我有这个代码:

class Window(QtGui.QMainWindow):
def __init__(self):
super(Window, self).__init__()
self.setGeometry(750, 450, 400, 200)
self.setFixedSize(self.size())
btn1 = QtGui.QPushButton("Convert", self)
btn1.move(210,171)
btn1.clicked.connect(self.progbar)

def progbar (self):
self.prog_win = QDialog()
self.prog_win.resize(400, 100)
self.prog_win.setFixedSize(self.prog_win.size())
self.prog_win.setWindowTitle("Processing request")
self.lbl = QLabel(self.prog_win)
self.lbl.setText("Please Wait. . .")
self.lbl.move(15,18)
self.progressBar = QtGui.QProgressBar(self.prog_win)
self.progressBar.resize(410, 25)
self.progressBar.move(15, 40)
self.progressBar.setRange(0,1)
self.myLongTask = TaskThread()

#I think this is where I am wrong
#because all of the answers here is very specific
#or just not for beginners
self.prog_win.show()
self.myLongTask.taskFinished.connect(self.onStart)
self.output_settings()

def onStart(self):
self.progressBar.setRange(0,0)
self.myLongTask.start()

def output_convert(self):
#very long process to convert a txt file to excel

#My Thread
class TaskThread(QtCore.QThread):
taskFinished = QtCore.pyqtSignal()
def run(self):
time.sleep(3)
self.taskFinished.emit()

def run():
app = QtGui.QApplication(sys.argv)
GUI = Window()
app.exec_()
run()

这里的所有示例和帖子对于理解进度条的实现都非常有帮助,但是所有示例都有针对特定问题的具体答案,我无法理解标准 pyqt 应用程序中进度条的实现。你们至少能指出我正确的方向吗?将不胜感激。

最佳答案

这是一个非常基本的进度条,仅使用最低限度所需的内容。

将整个示例读完是明智的做法。

import sys
import time

from PyQt5.QtWidgets import (QApplication, QDialog,
QProgressBar, QPushButton)

TIME_LIMIT = 100

class Actions(QDialog):
"""
Simple dialog that consists of a Progress Bar and a Button.
Clicking on the button results in the start of a timer and
updates the progress bar.
"""
def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setWindowTitle('Progress Bar')
self.progress = QProgressBar(self)
self.progress.setGeometry(0, 0, 300, 25)
self.progress.setMaximum(100)
self.button = QPushButton('Start', self)
self.button.move(0, 30)
self.show()

self.button.clicked.connect(self.onButtonClick)

def onButtonClick(self):
count = 0
while count < TIME_LIMIT:
count += 1
time.sleep(1)
self.progress.setValue(count)

if __name__ == "__main__":
app = QApplication(sys.argv)
window = Actions()
sys.exit(app.exec_())

进度条首先像这样导入 from PyQt5.QtWidgets import QProgressBar

然后它像QtWidgets中的任何其他小部件一样被初始化

self.progress.setGeometry(0, 0, 300, 25)方法定义了对话框上的x,y位置以及进度的宽度和高度酒吧。

然后,我们使用 .move() 将按钮向下移动 30px,这样两个小部件之间就会有 5px 的间隙.

这里使用self.progress.setValue(count)来更新进度。使用 .setMaximum() 设置最大值也会自动为您计算值。例如,如果最大值设置为 50,则由于 TIME_LIMIT 为 100,它将每秒从 0% 跳到 2% 到 4%,而不是从 0% 跳到 1% 到 2%。您还可以使用 .setMinimum() 设置最小值,强制进度条从给定值开始。

执行该程序将产生与此类似的 GUI。

Progress Bar Dialog Not Responding

正如您所看到的,GUI 肯定会卡住并且无响应,直到计数器满足 TIME_LIMIT 条件。这是因为 time.sleep 导致操作系统认为程序已陷入无限循环。

QThread

那么我们如何克服这个问题呢?我们可以使用PyQt5提供的线程类。

import sys
import time

from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import (QApplication, QDialog,
QProgressBar, QPushButton)

TIME_LIMIT = 100

class External(QThread):
"""
Runs a counter thread.
"""
countChanged = pyqtSignal(int)

def run(self):
count = 0
while count < TIME_LIMIT:
count +=1
time.sleep(1)
self.countChanged.emit(count)

class Actions(QDialog):
"""
Simple dialog that consists of a Progress Bar and a Button.
Clicking on the button results in the start of a timer and
updates the progress bar.
"""
def __init__(self):
super().__init__()
self.initUI()

def initUI(self):
self.setWindowTitle('Progress Bar')
self.progress = QProgressBar(self)
self.progress.setGeometry(0, 0, 300, 25)
self.progress.setMaximum(100)
self.button = QPushButton('Start', self)
self.button.move(0, 30)
self.show()

self.button.clicked.connect(self.onButtonClick)

def onButtonClick(self):
self.calc = External()
self.calc.countChanged.connect(self.onCountChanged)
self.calc.start()

def onCountChanged(self, value):
self.progress.setValue(value)

if __name__ == "__main__":
app = QApplication(sys.argv)
window = Actions()
sys.exit(app.exec_())

让我们分解一下这些修改。

from PyQt5.QtCore import QThread, pyqtSignal

这一行导入了Qthread,它是一个PyQt5实现,用于在后台划分和运行程序的某些部分(例如:函数、类)(也称为多线程) - 线程)。这些部分也称为线程。默认情况下,所有 PyQt5 程序都有一个主线程,其他线程(工作线程)用于将额外耗时和处理密集的任务转移到后台,同时仍然保持主程序正常运行。

第二个导入pyqtSignal用于在工作线程和主线程之间发送数据(信号)。在本例中,我们将使用它来告诉主线程更新进度条。

现在我们已将计数器的 while 循环移至名为 External 的单独类中。

class External(QThread):
"""
Runs a counter thread.
"""
countChanged = pyqtSignal(int)

def run(self):
count = 0
while count < TIME_LIMIT:
count +=1
time.sleep(1)
self.countChanged.emit(count)

通过子类化QThread,我们实质上是将External转换为可以在单独线程中运行的类。线程还可以随时启动或停止,这增加了它的好处。

这里 countChanged 是当前进度,pyqtSignal(int) 告诉工作线程发送的信号是 int 类型。而 self.countChanged.emit(count) 只是将信号发送到主线程中的任何连接(通常它也可以用于与其他工作线程通信)。

def onButtonClick(self):
self.calc = External()
self.calc.countChanged.connect(self.onCountChanged)
self.calc.start()

def onCountChanged(self, value):
self.progress.setValue(value)

当单击按钮时,self.onButtonClick 将运行并启动线程。线程通过 .start() 启动。还应该注意的是,我们将之前创建的信号 self.calc.countChanged 连接到用于更新进度条值的方法。每次更新 External::run::count 时,int 值也会发送到 onCountChanged

这就是进行这些更改后 GUI 的外观。

QThread Progress Bar

它还应该感觉更加灵敏并且不会卡住。

关于Python pyqt 多线程脉冲进度条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45157006/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com