Wie kann ich einen Arbeiter -Thread Signale empfangen lassen?Python

Python-Programme
Anonymous
 Wie kann ich einen Arbeiter -Thread Signale empfangen lassen?

Post by Anonymous »

Ich erstelle eine PYQT6 -Anwendung, die eine Sequenz im Hintergrund ausführen kann. Die Sequenz ist eine Unterklasse von QObject mit einer Run () -Methode, die von einem QThread aufgerufen wird. Hier ist das Problem: Die Sequenz kann keine Signale empfangen. Es gibt Signale für eine Pause, Unpause und Stornierung. Wenn ich die Sequenz starte, verlinke ich diese Signale mit Schaltflächen im Hauptfaden. Das Drücken dieser Tasten tut jedoch nichts. Die Schaltflächensignale sind ordnungsgemäß emittiert, aber der Worker -Thread empfängt sie nie. Bei all meiner Suche habe ich zwei Lösungen gefunden: (1) Verwenden Sie einen Qtimer , um Ereignisse im Arbeiter auszuführen, anstatt in einer Weile Loop, so dass die Ereignisschleife nicht blockiert ist, oder (2) qcoreApplication aufrufen. Mach es, wenn es der einzige Weg ist. Ich habe gehört, dass die zweite Option eine schlechte Übung ist, weil sie möglicherweise nicht sicher thread ist (ich bin mir darüber immer noch nicht sicher), aber ich könnte es tun, weil ich sowieso häufig zwischen den Sequenzaktionen warte. Könnte ich beispielsweise nur Ereignisse im Worker -Thread verarbeiten, nicht in der gesamten Anwendung?

Code: Select all

import sys
import time
from PyQt6.QtCore import Qt, pyqtSignal, QObject, QThread, QReadLocker, QWriteLocker, QReadWriteLock
from PyQt6.QtWidgets import (
QApplication,
QLabel,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget,
)

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

cancelCommand = pyqtSignal()

def __init__(self):
super().__init__()
self.canceled = False
self.paused = False
self.mutex = QReadWriteLock()

def run(self):
"""Long-running task."""
for i in range(10):
# this gets properly processed.  Why?
self.progress.emit(i)
time.sleep(1)
with QReadLocker(self.mutex):
if self.canceled:
break
while True:
with QReadLocker(self.mutex):
if not self.paused:
break
time.sleep(0.1)

self.finished.emit()

def cancel(self):
# this never runs
with QWriteLocker(self.mutex):
self.canceled = True

def pause(self):
# this never runs
with QWriteLocker(self.mutex):
self.paused = True

def unpause(self):
# this never runs
with QWriteLocker(self.mutex):
self.paused = False

class Window(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.clicksCount = 0
self.setupUi()

def setupUi(self):
self.setWindowTitle("Freezing GUI")
self.resize(300, 150)
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
# Create and connect widgets
self.clicksLabel = QLabel("Counting: 0 clicks", self)
self.clicksLabel.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
self.stepLabel = QLabel("Long-Running Step: 0")
self.stepLabel.setAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)
self.countBtn = QPushButton("Click me!", self)
self.countBtn.clicked.connect(self.countClicks)
self.longRunningBtn = QPushButton("Long-Running Task!", self)
self.longRunningBtn.clicked.connect(self.runLongTask)

self.cancel_button = QPushButton("Cancel", self)
self.pause_button = QPushButton("Pause", self)
self.unpause_button = QPushButton("Unpause", self)
# Set the layout
layout = QVBoxLayout()
layout.addWidget(self.clicksLabel)
layout.addWidget(self.countBtn)
layout.addStretch()
layout.addWidget(self.stepLabel)
layout.addWidget(self.longRunningBtn)
layout.addWidget(self.cancel_button)
layout.addWidget(self.pause_button)
layout.addWidget(self.unpause_button)
self.centralWidget.setLayout(layout)

def countClicks(self):
self.clicksCount += 1
self.clicksLabel.setText(f"Counting: {self.clicksCount} clicks")

def reportProgress(self, n):
self.stepLabel.setText(f"Long-Running Step: {n}")

def runLongTask(self):
# Step 2: Create a QThread object
self.threader = QThread()
# Step 3: Create a worker object
self.worker = Worker()
# Step 4: Move worker to the thread
self.worker.moveToThread(self.threader)
# Step 5: Connect signals and slots
self.threader.started.connect(self.worker.run)
self.worker.finished.connect(self.threader.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.threader.finished.connect(self.threader.deleteLater)
self.worker.progress.connect(self.reportProgress)
# these three signals never get received
self.cancel_button.pressed.connect(self.worker.cancel)
self.pause_button.pressed.connect(self.worker.pause)
self.unpause_button.pressed.connect(self.worker.unpause)

# Step 6: Start the thread
self.threader.start()
# Final resets
self.longRunningBtn.setEnabled(False)
self.threader.finished.connect(lambda: self.stepLabel.setText("Long-Running Step: 0"))

app = QApplication(sys.argv)
win = Window()
win.show()
sys.exit(app.exec())

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post