QProgressBar在使用PyQt5的过程中发生错误。

huangapple go评论63阅读模式
英文:

error while using QProgressbar PyQt5 python

问题

我有以下代码,在其中我实现了一个QProgressDialog,第一次按“开始”按钮运行create函数时它运行正常,但如果对话框完成并尝试再次运行它,它会显示一个不增加进度的空进度条。有任何想法吗?

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
import time

class Worker(QObject):
    signal = pyqtSignal(int)

    def __init__(self):
        super().__init__()

    @pyqtSlot()
    def do_work(self) -> None:
        for value in range(1, 101):
            self.signal.emit(value)
            time.sleep(0.01)

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.layout = QVBoxLayout()
        self.con = QWidget()
        self.setCentralWidget(self.con)
        self.con.setLayout(self.layout)
        self.btn = QPushButton("开始", self)
        self.layout.addWidget(self.btn)
        self.thread = QThread()
        self.thread.finished.connect(self.thread_finished)
        self.btn.pressed.connect(self.create)

    def create(self):
        self.p = QProgressDialog("进度", "取消", 0, 100)
        self.p.setValue(0)
        self.p.setWindowModality(Qt.ApplicationModal)
        self.p.canceled.connect(self.p.deleteLater)
        self.p.show()
        self.worker = Worker()
        self.worker.signal.connect(self.p.setValue)
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.do_work)
        self.thread.start()

    def thread_finished(self):
        self.thread.deleteLater()

app = QApplication(sys.argv)
window = Window()
window.show()
app.exec_()

我尝试将对话框设为局部变量,但也不起作用。

英文:

i have the following code in which I implemented a QprogressDialog it works fine the first time I press the Start button to run the create function but if the dialog finishes and I try to run it again it shows an empty bar that does not increases the progress. any ideas?

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
import time


class Worker(QObject):
    signal = pyqtSignal(int)

    def __init__(self):
        super().__init__()
    @pyqtSlot()
    def do_work(self) -> None:
        for value in range(1,101):
            self.signal.emit(value)
            time.sleep(0.01)
        

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.layout = QVBoxLayout()
        self.con = QWidget()
        self.setCentralWidget(self.con)
        self.con.setLayout(self.layout)
        self.btn = QPushButton("Start",self)
        self.layout.addWidget(self.btn)
        self.thread = QThread()
        self.thread.finished.connect(self.thread_finished)
        self.btn.pressed.connect(self.create)


    def create(self):
        self.p = QProgressDialog("Names", "Cancel", 0, 100)
        self.p.setValue(0)
        self.p.setWindowModality(Qt.ApplicationModal)
        self.p.canceled.connect(self.p.deleteLater)
        self.p.show()
        self.worker = Worker()
        self.worker.signal.connect(self.p.setValue)
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.do_work)
        self.thread.start()

        
        
    def thread_finished(self):
        self.thread.deletelater()
        # self.thread = QThread()
        # self.thread.finished.connect(self.thread_finished)



app = QApplication(sys.argv)
window = Window()
window.show()
app.exec_()

i tried making the dialog a local variable but it does not work either

答案1

得分: 2

do_work完成后,它只是返回,但线程仍然存活,因此当你再次调用start()时,不会发生任何事情:

如果线程已经在运行,此函数什么也不做。

此外,删除和重新创建对话框或线程是没有意义的。最多,你需要重新创建工作线程(假设它具有一些实例属性,如果重新启动将不再使用),但最重要的部分是,你必须在函数结束时告诉线程使用工作线程对象中的一个信号来 quit()

class Worker(QObject):
    signal = pyqtSignal(int)
    finished = pyqtSignal()

    @pyqtSlot()
    def do_work(self) -> None:
        self.keepRunning = True
        for value in range(1, 101):
            if not self.keepRunning:
                break
            self.signal.emit(value)
            time.sleep(0.01)
        self.finished.emit()

    def stop(self):
        self.keepRunning = False


class Window(QMainWindow):
    def __init__(self):
        # ...
        self.p = QProgressDialog("Names", "Cancel", 0, 100)
        self.p.setWindowModality(Qt.ApplicationModal)

    def create(self):
        self.p.show()

        self.worker = Worker()
        self.worker.signal.connect(self.p.setValue)
        self.p.canceled.connect(self.worker.stop)

        self.worker.moveToThread(self.thread)
        self.worker.finished.connect(self.thread.quit)

        self.thread.started.connect(self.worker.do_work)
        self.thread.finished.connect(self.worker.deleteLater)
        self.thread.start()

注意:你遇到的问题是一个问题,而不是一个错误。

英文:

When do_work finishes, it just returns, but the thread is still alive, so nothing happens when you call again start():

> If the thread is already running, this function does nothing.

Besides, deleting and recreating the dialog or the thread is pointless. At most, you need to recreate the worker (assuming it has some instance attributes that will not be used again if restarted), but the most important part is that you have to tell the thread to quit() when your function ends, using a signal in the worker object.

class Worker(QObject):
    signal = pyqtSignal(int)
    finished = pyqtSignal()

    @pyqtSlot()
    def do_work(self) -> None:
        self.keepRunning = True
        for value in range(1,101):
            if not self.keepRunning:
                break
            self.signal.emit(value)
            time.sleep(0.01)
        self.finished.emit()

    def stop(self):
        self.keepRunning = False


class Window(QMainWindow):
    def __init__(self):
        # ...
        self.p = QProgressDialog("Names", "Cancel", 0, 100)
        self.p.setWindowModality(Qt.ApplicationModal)

    def create(self):
        self.p.show()

        self.worker = Worker()
        self.worker.signal.connect(self.p.setValue)
        self.p.canceled.connect(self.worker.stop)

        self.worker.moveToThread(self.thread)
        self.worker.finished.connect(self.thread.quit)

        self.thread.started.connect(self.worker.do_work)
        self.thread.finished.connect(self.worker.deleteLater)
        self.thread.start()

<sup>Note: what you had was a problem, not an error.</sup>

huangapple
  • 本文由 发表于 2023年1月9日 06:24:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75051686.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定