Sto cercando di capire come utilizzare la segnalazione da un Qthread all'interfaccia Gui avviata.Come segnalare un QThread in esecuzione al PyQt Gui che lo ha avviato?
Configurazione: ho un processo (una simulazione) che deve essere eseguito quasi indefinitamente (o almeno per lunghi periodi di tempo)., Mentre è in esecuzione, esegue vari calcoli, e alcuni dei risultati devono essere rimandati alla GUI, che li visualizzerà in modo appropriato in tempo reale. Sto usando PyQt per la GUI. Inizialmente ho provato ad usare il modulo di threading di python, poi sono passato a QThreads dopo aver letto diversi post sia qui su SO che altrove.
In base a questo post sul Qt Blog You're doing it wrong, il modo migliore per utilizzare QThread è creare un QObject e quindi spostarlo in un Qthread. Così ho seguito il consiglio in Thread di riempimento con QThread in PyQt "> questa domanda SO e ho provato una semplice app di test (codice di seguito): apre una semplice GUI, consente di avviare il processo in background e emette un aggiornamento del valore del passo in ... una casella numerica
Ma non funziona L'interfaccia grafica è mai aggiornato che cosa sto facendo di sbagliato
import time, sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class SimulRunner(QObject):
'Object managing the simulation'
stepIncreased = pyqtSignal(int, name = 'stepIncreased')
def __init__(self):
super(SimulRunner, self).__init__()
self._step = 0
self._isRunning = True
self._maxSteps = 20
def longRunning(self):
while self._step < self._maxSteps and self._isRunning == True:
self._step += 1
self.stepIncreased.emit(self._step)
time.sleep(0.1)
def stop(self):
self._isRunning = False
class SimulationUi(QDialog):
'PyQt interface'
def __init__(self):
super(SimulationUi, self).__init__()
self.goButton = QPushButton('Go')
self.stopButton = QPushButton('Stop')
self.currentStep = QSpinBox()
self.layout = QHBoxLayout()
self.layout.addWidget(self.goButton)
self.layout.addWidget(self.stopButton)
self.layout.addWidget(self.currentStep)
self.setLayout(self.layout)
self.simulRunner = SimulRunner()
self.simulThread = QThread()
self.simulRunner.moveToThread(self.simulThread)
self.simulRunner.stepIncreased.connect(self.currentStep.setValue)
self.connect(self.stopButton, SIGNAL('clicked()'), self.simulRunner.stop)
self.connect(self.goButton, SIGNAL('clicked()'), self.simulThread.start)
self.connect(self.simulRunner,SIGNAL('stepIncreased'), self.currentStep.setValue)
if __name__ == '__main__':
app = QApplication(sys.argv)
simul = SimulationUi()
simul.show()
sys.exit(app.exec_())
Hai perfettamente ragione, ho appena realizzato l'errore. Ho tagliato e incollato il codice da una versione precedente in cui stavo sottoclasse Qthread invece di usare moveToThread e mi sono completamente dimenticato del metodo started(). Grazie per segnalarlo. – stefano
questo è un esempio molto interessante. Comunque segui questo suggerimento il thread inizia ma il pulsante stop non lo ferma. Sarebbe bello avere un esempio funzionante. E forse un pulsante Go che può riavviare il tutto – Fabrizio
Lo stop invia semplicemente un segnale, ma come 'simulThread' è occupato nell'esecuzione di' longRunning', quel segnale può essere processato solo dopo che quel metodo è terminato, ecco perché non lo fa fermare il contatore. Per fare ciò, 'stop' dovrebbe essere chiamato da un thread diverso (ad esempio il thread principale del gui). Per riavviare il contatore, è necessario reimpostare il flag '_isRunning' se è stato arrestato, ma questo va oltre lo scopo originale della domanda. Tuttavia, ho pubblicato un esempio un po 'più completo [qui] (http://pastebin.com/kmvLb6Y2) (ci sarebbero ancora alcune cose che potrebbero essere migliorate ...) – mata