1

QThreads と Signals/Slots を使用して GUI と通信するプログラムがあります。これは、以下に示す単純化された形式を持っています。

ただし、マルチコア処理を利用できるように、これを QProcess に変更したいと考えています。これを行う簡単な方法はありますか?

単純に に変更QThreadすると、プロセスの機能QProcessがありません。モジュール内のやmoveToThread()など、マルチコア処理に対していくつかの異なるアプローチを試みてきましたが、うまく機能するものは何もありません。それで、私はすでにQtlandにいるので、使いやすいと思いました。Pipes()Queues()multiprocessingQProcess

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

1 に答える 1

2

moveToThread()プロセスは独自のメモリ空間に存在するため、プロセスにはありません。そのため、そのMainWindowメンバーを表示することはできません。使用を開始するアプリケーションは、QProcessスタンドアロン アプリケーションとして実行できる必要があります。

別の でスペクトルを実行するQProcessには、現在の MainWindow メンバーではなく、スペクトルを別の実行可能モジュールにする必要があります。

編集:

に最も依存しない自己完結型モジュールを定義する必要がありMainWindowます。これは、スペクトル プロセスのみ、またはタブを使用したスペクトル プロセスにすることができます。構築時または標準入力を介してプロセスに情報を渡し、標準出力を介してプロセスからデータを取得できます。プロセスを配置する弁護士を選択する際の重要なアイデアは、プロセスと MainWindow 間の通信と依存関係を最小限に抑えることです。プロセスは単純な C プログラムと考えることができます。

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

起動時に引数を渡し、必要に応じて cin/stdin を介して MainWindow から追加の入力を取得しMainWindow、cout/stdout/stderr を介していくつかの結果を出力できます (QProcessそのためのインターフェイスがあります)。

于 2013-03-28T16:54:31.860 に答える