Esempio di Segnali e Slot con QThread su PySide
Inviato da Matteo Mattei ~ 28th agosto 2011
In questi giorni ho iniziato a studiare PySide. Dopo alcuni giorni spesi a leggere un bel po’ di materiale online, ho pensato che un esempio reale potesse essere utile per chi come come me intende cimentarsi con PySide. In questo esempio vi vieme mostrato come potete implementare un segnale custom (MySignal) insieme all’uso dei thread con QThread.
Il codice seguente crea una finestra con due pulsanti: il primo avvia e ferma un thread (MyThread) che lancia un processo il quale stampa sullo standard output della console un punto ogni secondo continuamente. Il secondo bottone vi permette solo di avviare un altro thread (MyLongThread) che stampa un asterisco sullo standard output ogni secondo per 10 secondi e poi esce.
Questo esempio utilizza la versione delle API 2 (introdotta con PyQt 4.5) per connettere i segnali agli slot.
#!/usr/bin/env python2
import sys, time
from PySide.QtGui import *
from PySide.QtCore import *
class MySignal(QObject):
sig = Signal(str)
class MyLongThread(QThread):
def __init__(self, parent = None):
QThread.__init__(self, parent)
self.exiting = False
self.signal = MySignal()
def run(self):
end = time.time()+10
while self.exiting==False:
sys.stdout.write('*')
sys.stdout.flush()
time.sleep(1)
now = time.time()
if now>=end:
self.exiting=True
self.signal.sig.emit('OK')
class MyThread(QThread):
def __init__(self, parent = None):
QThread.__init__(self, parent)
self.exiting = False
def run(self):
while self.exiting==False:
sys.stdout.write('.')
sys.stdout.flush()
time.sleep(1)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self,parent)
self.centralwidget = QWidget(self)
self.batchbutton = QPushButton('Start batch',self)
self.longbutton = QPushButton('Start long (10 seconds) operation',self)
self.label1 = QLabel('Continuos batch')
self.label2 = QLabel('Long batch')
self.vbox = QVBoxLayout()
self.vbox.addWidget(self.batchbutton)
self.vbox.addWidget(self.longbutton)
self.vbox.addWidget(self.label1)
self.vbox.addWidget(self.label2)
self.setCentralWidget(self.centralwidget)
self.centralwidget.setLayout(self.vbox)
self.thread = MyThread()
self.longthread = MyLongThread()
self.batchbutton.clicked.connect(self.handletoggle)
self.longbutton.clicked.connect(self.longoperation)
self.thread.started.connect(self.started)
self.thread.finished.connect(self.finished)
self.thread.terminated.connect(self.terminated)
self.longthread.signal.sig.connect(self.longoperationcomplete)
def started(self):
self.label1.setText('Continuous batch started')
def finished(self):
self.label1.setText('Continuous batch stopped')
def terminated(self):
self.label1.setText('Continuous batch terminated')
def handletoggle(self):
if self.thread.isRunning():
self.thread.exiting=True
self.batchbutton.setEnabled(False)
while self.thread.isRunning():
time.sleep(0.01)
continue
self.batchbutton.setText('Start batch')
self.batchbutton.setEnabled(True)
else:
self.thread.exiting=False
self.thread.start()
self.batchbutton.setEnabled(False)
while not self.thread.isRunning():
time.sleep(0.01)
continue
self.batchbutton.setText('Stop batch')
self.batchbutton.setEnabled(True)
def longoperation(self):
if not self.longthread.isRunning():
self.longthread.exiting=False
self.longthread.start()
self.label2.setText('Long operation started')
self.longbutton.setEnabled(False)
def longoperationcomplete(self,data):
self.label2.setText('Long operation completed with: '+data)
self.longbutton.setEnabled(True)
if __name__=='__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Per ulteriori informazioni potete dare un’occhiata ai seguenti link:
Documentazione sul modulo QThread: http://doc.qt.nokia.com/latest/qthread.html
Segnali e Slot di PySide: http://developer.qt.nokia.com/wiki/Signals_and_Slots_in_PySide
PyQt Api 2 con PySide: http://www.pyside.org/docs/pseps/psep-0101.html