【问题标题】:QThread Signals/Slots to QProcessesQThread 信号/槽到 QProcesses
【发布时间】:2013-03-28 15:22:44
【问题描述】:

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

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

如果我只是将 QThread 更改为 QProcess ,则进程没有 moveToThread() 函数。我一直在尝试几种不同的多核处理方法,例如multiprocessing 模块中的Pipes()Queues(),但我无法让任何东西很好地工作。所以,我认为使用 QProcess 会更容易,因为我已经在 Qtland。

这是我为QThreads、信号和插槽提供的简化代码。

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_())

【问题讨论】:

    标签: python qt user-interface multiprocessing


    【解决方案1】:

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

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

    编辑:

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

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

    你可以在启动时传递参数,必要时通过 cin/stdin 从 MainWindow 获取额外的输入,通过 cout/stdout/stderr 将一些结果输出到MainWindowQProcess 有接口)。

    【讨论】:

    • 谢谢@ilya,我想我理解你所说的进程不在同一个内存空间上。但是,如果主窗口通过打开文件和检索数据来创建光谱对象,则该窗口将不得不聚合光谱类型对象,不是吗?解决方案是创建选项卡对象并将 X、Y 数据传递给一个单独的 Spectra 对象吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    相关资源
    最近更新 更多