Skip to content

Instantly share code, notes, and snippets.

@haccks
Created September 29, 2023 19:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save haccks/0fec103be10a963d49d050df86e87547 to your computer and use it in GitHub Desktop.
Save haccks/0fec103be10a963d49d050df86e87547 to your computer and use it in GitHub Desktop.
QThread Demo
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()
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()
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