Domanda

Ho un programma PyQt, in questo programma inizio un nuovo thread per disegnare un'immagine complicata. Voglio sapere quando il thread è terminato in modo da poter stampare l'immagine sul modulo.

L'unico ostacolo che sto affrontando è che devo invocare il metodo di disegno dall'interno del thread della GUI, quindi voglio un modo per dire al thread della GUI di fare qualcosa dall'interno del thread del disegno.

Potrei farlo usando un thread ma il programma si interrompe.

Lo facevo in C # usando un BackgroundWorker che aveva un evento per finire.

C'è un modo per fare una cosa del genere in Python? o dovrei hackerare il ciclo principale dell'applicazione PyQt e cambiarlo un po '?

È stato utile?

Soluzione

Negli esempi con PyQt-Py2.6-gpl-4.4.4-2 .exe , c'è l'app Mandelbrot. Nella mia installazione, l'origine è in C: \ Python26 \ Lib \ site-pacchetti \ PyQt4 \ esempi \ thread \ mandelbrot.pyw. Usa un thread per rendere la pixmap e un segnale (cerca nel codice QtCore.SIGNAL) per dire al thread della GUI che è il momento di disegnare. Sembra quello che vuoi.

Altri suggerimenti

Ho avuto un problema simile con uno dei miei progetti e ho usato i segnali per dire al mio thread GUI principale quando visualizzare i risultati del lavoratore e aggiornare una barra di avanzamento.

Nota che ci sono diversi esempi per connettere oggetti e segnali nel guida di riferimento di PyQt . Non tutti si applicano a Python (mi ci è voluto un po 'per realizzarlo).

Ecco gli esempi che si desidera esaminare per collegare un segnale Python a una funzione Python.

QtCore.QObject.connect(a, QtCore.SIGNAL("PySig"), pyFunction)
a.emit(QtCore.SIGNAL("pySig"), "Hello", "World")

Inoltre, non dimenticare di aggiungere __pyqtSignals__ = (" PySig " ;,) alla tua classe lavoratrice.

Ecco una versione ridotta di quello che ho fatto:

class MyGui(QtGui.QMainWindow):

    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.worker = None

    def makeWorker(self):
        #create new thread
        self.worker = Worker(work_to_do)
        #connect thread to GUI function
        QtCore.QObject.connect(self.worker, QtCore.SIGNAL('progressUpdated'), self.updateWorkerProgress)
        QtCore.QObject.connect(self.worker, QtCore.SIGNAL('resultsReady'), self.updateResults)
        #start thread
        self.worker.start()

    def updateResults(self):
        results = self.worker.results
        #display results in the GUI

    def updateWorkerProgress(self, msg)
        progress = self.worker.progress
        #update progress bar and display msg in status bar


class Worker(QtCore.QThread):

    __pyqtSignals__ = ( "resultsReady", 
                        "progressUpdated" )

    def __init__(self, work_queue):
        self.progress = 0  
        self.results = []
        self.work_queue = work_queue
        QtCore.QThread.__init__(self, None)

    def run(self):
        #do whatever work
        num_work_items = len(self.work_queue)
        for i, work_item in enumerate(self.work_queue):
            new_progress = int((float(i)/num_work_items)*100)
            #emit signal only if progress has changed
            if self.progress != new_progress:
                self.progress = new_progress
                self.emit(QtCore.SIGNAL("progressUpdated"), 'Working...')
            #process work item and update results
            result = processWorkItem(work_item)
            self.results.append(result)
        self.emit(QtCore.SIGNAL("resultsReady"))

Credo che il tuo thread di disegno possa inviare un evento al thread principale usando QApplication.postEvent. Devi solo scegliere un oggetto come destinatario dell'evento. Ulteriori informazioni

Ampliamento della risposta di Jeff: la Qt documentazione su thread support afferma che è possibile far eseguire i gestori di eventi (slot in Qt parlance) nel thread che "possiede" un oggetto.

Quindi, nel tuo caso, dovresti definire uno slot printImage (QImage) sul modulo e un segnale doneDrawing (QImage) su qualunque cosa stia creando l'immagine, e collegarli semplicemente usando una coda o una connessione automatica.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top