QThread信号/插槽到QProcesses [英] QThread Signals/Slots to QProcesses

查看:105
本文介绍了QThread信号/插槽到QProcesses的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用QThreads和Signals/Slots与GUI进行通信的程序. 它具有如下所示的简化形式.

I have a program which uses QThreads and Signals/Slots to communicate to a GUI. It has the simplified form shown below.

但是,我想将其更改为QProcess,以便可以利用多核处理.有没有简单的方法可以做到这一点?

However, I would like to change this to a QProcess so that I can take advantage of multicore processing. Is there a simple way to do this?

如果仅将QThread更改为QProcess,则没有用于进程的moveToThread()功能.我一直在尝试几种不同的方法来进行多核处理,例如multiprocessing模块中的Pipes()Queues(),但是我无法获得任何效果.因此,我认为使用QProcess会更容易,因为我已经在Qtland.

If I simply change QThread to QProcess , there is no moveToThread() function for processes. I have been trying several different approaches to multicore processing, such as Pipes() and Queues() in the multiprocessing module, but I can't get anything to work very well. So, I figured it would be easier to use QProcess since I am already in Qtland.

这是我为QThreads,信号和插槽使用的简化代码.

Here is the simplified code I have for QThreads, signals and slots.

from PyQt4 import QtCore, QtGui
import multiprocessing as mp
import numpy as np
import sys

class Spectra(QtCore.QObject):

    update_signal = QtCore.pyqtSignal(str)
    done_signal = QtCore.pyqtSignal()

    def __init__(self, spectra_name, X, Y):
        QtCore.QObject.__init__(self)
        self.spectra_name = spectra_name
        self.X = X
        self.Y = Y
        self.iteration = 0

    @QtCore.pyqtSlot() 
    def complex_processing_on_spectra(self):
        for i in range(0,99999):
            self.iteration += 1
            self.update_signal.emit(str(self.iteration))
        self.done_signal.emit()

class Spectra_Tab(QtGui.QTabWidget):
    start_comp = QtCore.pyqtSignal()
    kill_thread = QtCore.pyqtSignal()
    def __init__(self, parent, spectra):
        self.parent = parent
        self.spectra = spectra
        QtGui.QTabWidget.__init__(self, parent)

        self.treeWidget = QtGui.QTreeWidget(self)
        self.properties = QtGui.QTreeWidgetItem(self.treeWidget, ["Properties"])
        self.step = QtGui.QTreeWidgetItem(self.properties, ["Iteration #"])

        thread = QtCore.QThread(parent=self)
        self.worker = self.spectra
        self.worker.moveToThread(thread)
        self.worker.update_signal.connect(self.update_GUI)
        self.worker.done_signal.connect(self.closeEvent)
        self.start_comp.connect(self.worker.complex_processing_on_spectra)
        self.kill_thread.connect(thread.quit)
        thread.start()

    @QtCore.pyqtSlot(str)
    def update_GUI(self, iteration):
        self.step.setText(0, iteration)

    def start_computation(self):
        self.start_comp.emit()

    def closeEvent(self):
        print 'done with processing'
        self.kill_thread.emit()

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

        self.setTabShape(QtGui.QTabWidget.Rounded)
        self.centralwidget = QtGui.QWidget(self)
        self.top_level_layout = QtGui.QGridLayout(self.centralwidget)

        self.tabWidget = QtGui.QTabWidget(self.centralwidget)
        self.top_level_layout.addWidget(self.tabWidget, 1, 0, 25, 25)

        process_button = QtGui.QPushButton("Process")
        self.top_level_layout.addWidget(process_button, 0, 1)
        QtCore.QObject.connect(process_button, QtCore.SIGNAL("clicked()"), self.process)

        self.setCentralWidget(self.centralwidget)
        self.centralwidget.setLayout(self.top_level_layout)

        # Open several files in loop from button - simplifed to one here
        X = np.arange(0.1200,.2)
        Y = np.arange(0.1200,.2)
        self.spectra = Spectra('name', X, Y)
        self.spectra_tab = Spectra_Tab(self.tabWidget, self.spectra)
        self.tabWidget.addTab(self.spectra_tab, 'name')

    def process(self):
        self.spectra_tab.start_computation()
        return

if __name__ == "__main__":
    app = QtGui.QApplication([])
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())

推荐答案

进程没有moveToThread(),因为进程位于其自己的内存空间中,因此它看不到MainWindow或其任何成员.您开始使用QProcess的应用程序应该能够作为独立应用程序执行.

There is no moveToThread() for processes since a process lives in its own memory space, so it cannot see MainWindow or any of it members. The application that you start using QProcess should be able to execute as stand-alone application.

要在另一个QProcess中运行光谱,您将需要使光谱成为一个单独的可执行模块,而不是现在的MainWindow成员.

To run spectra in another QProcess, you will need to make spectra a separate executable module instead of MainWindow member as it is now.

您需要定义最不依赖MainWindow的自包含模块-它可以仅是光谱处理,也可以是带有tab的光谱处理.您可以通过构造或标准输入将信息传递到过程,并通过标准输出从过程中检索数据.选择律师加入流程的关键思想是尽量减少流程与MainWindow之间的沟通和依赖性.您可能将过程视为简单的C程序:

You need to define the self-contained module that is least dependent on the MainWindow - it can be spectra process only, or spectra process with tab. You can pass info to process either on construction, or through standard input, and retrieve data from process through standard output. Key idea when selecting lawyer to put process in is to minimize communication and dependency between the process and MainWindow. You may think of a process as simple C program:

int main(int argc,char* argv[]);

您可以在启动时传递参数,必要时通过cin/stdin从MainWindow获得其他输入,并通过cout/stdout/stderr将某些结果输出到MainWindow(QProcess具有该接口).

you can pass arguments on startup, get additional input from MainWindow through cin/stdin if necessary, output some results to MainWindow through cout/stdout/stderr (QProcess have interface for that).

这篇关于QThread信号/插槽到QProcesses的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆