These code files are part of the blog How to use QThread correctly.
Created
September 29, 2023 19:36
-
-
Save haccks/0fec103be10a963d49d050df86e87547 to your computer and use it in GitHub Desktop.
QThread Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import time | |
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, | |
QPushButton, QVBoxLayout, QProgressBar, | |
QHBoxLayout, QFrame) | |
from PySide6.QtCore import QThread, Signal, Slot, QMutex | |
class WorkerThread(QThread): | |
progress = Signal(int) | |
def __init__(self, n): | |
super().__init__() | |
self.n = n | |
self.is_cancel = False | |
self.mutex = QMutex() | |
@Slot() | |
def stop_download(self): | |
self.mutex.lock() | |
self.is_cancel = True | |
self.mutex.unlock() | |
def do_work(self): | |
for i in range(1, self.n + 1): | |
if self.is_cancel: | |
break | |
self.progress.emit(i) | |
time.sleep(1) | |
def run(self): | |
self.do_work() | |
class MainWindow(QMainWindow): | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
self.setGeometry(100, 100, 300, 50) | |
self.setWindowTitle('QThread Demo') | |
# setup widget | |
self.widget = QWidget() | |
layout_v = QVBoxLayout() | |
self.widget.setLayout(layout_v) | |
self.setCentralWidget(self.widget) | |
self.progress_bar = QProgressBar(self) | |
self.progress_bar.setValue(0) | |
self.download_btn = QPushButton(text='Download') | |
self.download_btn.clicked.connect(self.download) | |
self.cancel_btn = QPushButton(text='Cancel') | |
# self.cancel_btn.clicked.connect(self.cancel) | |
self.cancel_btn.setEnabled(False) | |
self.container_frame = QFrame() | |
layout_h = QHBoxLayout() | |
self.container_frame.setLayout(layout_h) | |
layout_h.addWidget(self.download_btn) | |
layout_h.addWidget(self.cancel_btn) | |
layout_v.addWidget(self.progress_bar) | |
# Add container_frame to layout_v | |
layout_v.addWidget(self.container_frame) | |
self.show() | |
@Slot() | |
def download(self): | |
num = 5 | |
self.download_btn.setEnabled(False) | |
self.cancel_btn.setEnabled(True) | |
self.progress_bar.reset() | |
self.progress_bar.setMaximum(num) | |
self.worker_thread = WorkerThread(num) | |
self.worker_thread.progress.connect(self.progress_bar.setValue) | |
self.worker_thread.finished.connect(self.finished) | |
self.worker_thread.finished.connect(self.worker_thread.deleteLater) | |
self.cancel_btn.clicked.connect(self.worker_thread.stop_download) | |
self.worker_thread.start() | |
# @Slot() | |
# def cancel(self): | |
# self.worker_thread.stop_download() | |
# # self.progress_bar.reset() | |
@Slot() | |
def finished(self): | |
self.progress_bar.reset() | |
self.download_btn.setEnabled(True) | |
self.cancel_btn.setEnabled(False) | |
if __name__ == '__main__': | |
app = QApplication(sys.argv) | |
window = MainWindow() | |
app.exec() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import time | |
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, | |
QPushButton, QVBoxLayout, QProgressBar, | |
QFrame, QHBoxLayout) | |
from PySide6.QtCore import QThread, QObject, Signal, Slot, QMutex | |
class Worker(QObject): | |
progress = Signal(int) | |
finished = Signal() | |
def __init__(self, n): | |
super().__init__() | |
self.n = n | |
self.is_cancel = False | |
self.mutex = QMutex() | |
def stop_download(self): | |
# self.mutex.lock() | |
self.is_cancel = True | |
# self.mutex.unlock() | |
@Slot() | |
def do_work(self): | |
for i in range(1, self.n + 1): | |
if self.is_cancel: | |
break | |
self.progress.emit(i) | |
time.sleep(1) | |
self.finished.emit() | |
class MainWindow(QMainWindow): | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
self.setGeometry(100, 100, 300, 50) | |
self.setWindowTitle('QThread Demo') | |
# setup widget | |
self.widget = QWidget() | |
layout_v = QVBoxLayout() | |
self.widget.setLayout(layout_v) | |
self.setCentralWidget(self.widget) | |
self.progress_bar = QProgressBar(self) | |
self.progress_bar.setValue(0) | |
self.download_btn = QPushButton(text='Download') | |
self.download_btn.clicked.connect(self.download) | |
self.cancel_btn = QPushButton(text='Cancel') | |
# self.cancel_btn.clicked.connect(self.cancel) | |
self.cancel_btn.setEnabled(False) | |
self.container_frame = QFrame() | |
layout_h = QHBoxLayout() | |
self.container_frame.setLayout(layout_h) | |
layout_h.addWidget(self.download_btn) | |
layout_h.addWidget(self.cancel_btn) | |
layout_v.addWidget(self.progress_bar) | |
layout_v.addWidget(self.container_frame) | |
# show the window | |
self.show() | |
def download(self): | |
self.download_btn.setEnabled(False) | |
self.cancel_btn.setEnabled(True) | |
num = 5 | |
self.progress_bar.reset() | |
self.progress_bar.setMaximum(num) | |
self.worker = Worker(num) | |
self.worker_thread = QThread() | |
self.worker.moveToThread(self.worker_thread) | |
self.worker.progress.connect(self.progress_bar.setValue) | |
self.worker.finished.connect(self.finished) | |
self.worker_thread.started.connect(self.worker.do_work) | |
# Free worker object from secondary thread | |
self.worker_thread.finished.connect(self.worker.deleteLater) | |
self.worker_thread.finished.connect(self.worker_thread.deleteLater) | |
self.cancel_btn.clicked.connect(self.cancel) | |
self.worker_thread.start() | |
@Slot() | |
def cancel(self): | |
self.worker.stop_download() | |
@Slot() | |
def finished(self): | |
self.progress_bar.reset() | |
self.download_btn.setEnabled(True) | |
self.cancel_btn.setEnabled(False) | |
self.worker_thread.quit() | |
self.worker_thread.wait() | |
if __name__ == '__main__': | |
app = QApplication(sys.argv) | |
window = MainWindow() | |
app.exec() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import time | |
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, | |
QPushButton, QVBoxLayout, QProgressBar, | |
QFrame, QHBoxLayout) | |
from PySide6.QtCore import QThread, QObject, Signal, Slot | |
class Worker(QObject): | |
progress = Signal(int) | |
finished = Signal() | |
def __init__(self, n): | |
super().__init__() | |
self.n = n | |
self.is_cancel = False | |
@Slot() | |
def stop_download(self): | |
self.is_cancel = True | |
# time.sleep(5) | |
@Slot() | |
def do_work(self): | |
for i in range(1, self.n + 1): | |
if self.is_cancel: | |
break | |
self.progress.emit(i) | |
time.sleep(1) | |
self.finished.emit() | |
class MainWindow(QMainWindow): | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
self.setGeometry(100, 100, 300, 50) | |
self.setWindowTitle('QThread Demo') | |
# setup widget | |
self.widget = QWidget() | |
layout_v = QVBoxLayout() | |
self.widget.setLayout(layout_v) | |
self.setCentralWidget(self.widget) | |
self.progress_bar = QProgressBar(self) | |
self.progress_bar.setValue(0) | |
self.download_btn = QPushButton(text='Download') | |
self.download_btn.clicked.connect(self.download) | |
self.cancel_btn = QPushButton(text='Cancel') | |
# self.cancel_btn.clicked.connect(self.cancel) | |
self.cancel_btn.setEnabled(False) | |
self.container_frame = QFrame() | |
layout_h = QHBoxLayout() | |
self.container_frame.setLayout(layout_h) | |
layout_h.addWidget(self.download_btn) | |
layout_h.addWidget(self.cancel_btn) | |
layout_v.addWidget(self.progress_bar) | |
layout_v.addWidget(self.container_frame) | |
# show the window | |
self.show() | |
def download(self): | |
self.download_btn.setEnabled(False) | |
self.cancel_btn.setEnabled(True) | |
num = 5 | |
self.progress_bar.reset() | |
self.progress_bar.setMaximum(num) | |
self.worker = Worker(num) | |
self.worker_thread = QThread() | |
self.worker.moveToThread(self.worker_thread) | |
self.worker.progress.connect(self.progress_bar.setValue) | |
self.worker.finished.connect(self.finished) | |
self.worker_thread.started.connect(self.worker.do_work) | |
self.worker_thread.finished.connect(self.worker.deleteLater) | |
self.worker_thread.finished.connect(self.worker_thread.deleteLater) | |
# self.cancelled.connect(self.worker.stop_download) | |
self.cancel_btn.clicked.connect(self.worker.stop_download) | |
self.worker_thread.start() | |
# @Slot() | |
# def cancel(self): | |
# self.cancelled.emit() | |
@Slot() | |
def finished(self): | |
self.download_btn.setEnabled(True) | |
self.cancel_btn.setEnabled(False) | |
self.worker_thread.quit() | |
self.worker_thread.wait() | |
self.progress_bar.reset() | |
if __name__ == '__main__': | |
app = QApplication(sys.argv) | |
window = MainWindow() | |
app.exec() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment