Вопрос

У меня есть программа PyQt, в этой программе я запускаю новый поток для рисования сложного изображения. Я хочу знать, когда закончится поток, чтобы я мог напечатать изображение в форме.

Единственное препятствие, с которым я сталкиваюсь, заключается в том, что мне нужно вызывать метод рисования из потока GUI, поэтому я хочу, чтобы поток GUI что-то делал из потока рисования.

Я мог бы сделать это, используя один поток, но программа останавливается.

Раньше я делал это в C #, используя BackgroundWorker, у которого было событие для завершения.

Есть ли способ сделать это в Python? или я должен взломать основной цикл приложения PyQt и немного его изменить?

Это было полезно?

Решение

В примерах с PyQt-Py2.6-gpl-4.4.4-2 .exe , есть приложение Mandelbrot. В моей установке исходный код находится в C: \ Python26 \ Lib \ site-packages \ PyQt4 \ examples \ threads \ mandelbrot.pyw. Он использует поток для визуализации растрового изображения и сигнала (ищите код QtCore.SIGNAL), чтобы сообщить потоку графического интерфейса о времени рисования. Похоже, что вы хотите.

Другие советы

У меня была похожая проблема с одним из моих проектов, и я использовал сигналы, чтобы сообщить моему основному потоку графического интерфейса, когда отображать результаты от работника и обновлять индикатор выполнения.

Обратите внимание, что в Справочное руководство по PyQt . Не все из них применимы к Python (мне понадобилось время, чтобы понять это).

Вот примеры, которые вы хотите посмотреть для подключения сигнала Python к функции Python.

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

Кроме того, не забудьте добавить __ pyqtSignals__ = (" PySig " ;,) в свой рабочий класс.

Вот урезанная версия того, что я сделал:

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"))

Я полагаю, что ваш поток рисования может отправить событие в основной поток с помощью QApplication.postEvent. Вам просто нужно выбрать какой-то объект в качестве получателя события. Подробнее

Более подробно об ответе Джеффа: документация Qt по поддержка потока утверждает, что можно заставить обработчики событий (слоты на языке Qt) исполняться в потоке, которому " принадлежит " объект.

Таким образом, в вашем случае вы определяете слот printImage (QImage) в форме и сигнал doneDrawing (QImage) для всего, что создает изображение, и просто подключаете их с помощью очереди или автоматического подключения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top