运行 QThread with PySide/PyQt 时禁用元素

Disable elements when running QThread with PySide/PyQt

这是我单击“确定”按钮时得到的结果。

但我想在 run_action() 仍然是 运行 时禁用这两个按钮,最后将 bar 重置为 0。

这是我当前的代码:

import sys
import time

from PySide6.QtCore import QThread, Signal
from PySide6.QtWidgets import (
    QApplication,
    QHBoxLayout,
    QProgressBar,
    QPushButton,
    QWidget,
)


class External(QThread):
    progressChanged = Signal(int)

    def run(self):
        progress = 0
        while progress < 100:
            progress += 10
            time.sleep(1)
            self.progressChanged.emit(progress)


class Window(QWidget):
    """The main application Window."""

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Example")

        self.layout = QHBoxLayout()
        self.layout.setContentsMargins(6, 6, 6, 6)

        self.bar = QProgressBar()
        self.bar.setTextVisible(False)
        self.bar.setValue(0)
        self.layout.addWidget(self.bar)

        self.cancel_btn = QPushButton("Cancel")
        self.cancel_btn.clicked.connect(self.close)
        self.layout.addWidget(self.cancel_btn)

        self.ok_btn = QPushButton("OK")
        self.ok_btn.clicked.connect(self.run_action)
        self.layout.addWidget(self.ok_btn)

        self.setLayout(self.layout)

    def run_action(self):
        self.ok_btn.setEnabled(False)
        self.cancel_btn.setEnabled(False)

        self.calc = External()
        self.calc.progressChanged.connect(self.onProgressChanged)
        self.calc.start()

        self.cancel_btn.setEnabled(True)
        self.ok_btn.setEnabled(True)
        self.bar.setValue(0)

    def onProgressChanged(self, value):
        self.bar.setValue(value)


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

void QThread::finished()

This signal is emitted from the associated thread right before it finishes executing.

When this signal is emitted, the event loop has already stopped running. No more events will be processed in the thread, except for deferred deletion events. This signal can be connected to QObject::deleteLater(), to free objects in that thread.

import sys
#import time

#from PySide6.QtCore import QThread, Signal
from PyQt5.QtCore import QThread, pyqtSignal

#from PySide6.QtWidgets import (
from PyQt5.QtWidgets import (
    QApplication,
    QHBoxLayout,
    QProgressBar,
    QPushButton,
    QWidget,
)


class External(QThread):
#    progressChanged = Signal(int)
    progressChanged = pyqtSignal(int)

    def run(self):
        progress = 0
        while progress <= 100:
            self.progressChanged.emit(progress)
            self.msleep(500)
            progress += 10


class Window(QWidget):
    """The main application Window."""

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Example")

        self.layout = QHBoxLayout()
        self.layout.setContentsMargins(6, 6, 6, 6)

        self.bar = QProgressBar()
        self.bar.setTextVisible(False)
        self.bar.setValue(0)
        self.layout.addWidget(self.bar)

        self.cancel_btn = QPushButton("Cancel")
        self.cancel_btn.clicked.connect(self.close)
        self.layout.addWidget(self.cancel_btn)

        self.ok_btn = QPushButton("OK")
        self.ok_btn.clicked.connect(self.run_action)
        self.layout.addWidget(self.ok_btn)

        self.setLayout(self.layout)

    def run_action(self):
        self.ok_btn.setEnabled(False)        
        self.cancel_btn.setEnabled(False)        

        self.calc = External()
        self.calc.progressChanged.connect(self.onProgressChanged)
        self.calc.finished.connect(self.onFinished)                     # +++
        self.calc.start()

#        self.cancel_btn.setEnabled(True)
#        self.ok_btn.setEnabled(True)
#        self.bar.setValue(0)

    def onProgressChanged(self, value):
        self.bar.setValue(value)

    def onFinished(self):                                               # +++
        self.cancel_btn.setEnabled(True)
        self.ok_btn.setEnabled(True)
        self.bar.setValue(0)        

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