Skip to main content
4 of 6
Rollback to Revision 2
Jamal
  • 34.8k
  • 13
  • 133
  • 237

Pausing and Manipulating Data in a Process using multiprocessing.Pipe with a GUI

I need help with the design of my code, and I believe it is the reason why I cannot acheive what I am trying to do. I have been trying for quite some time to figure out why this script will not work.

What I am Trying to do:

I am trying to get a GUI to not lock while allocating processes to a bunch of tabs (number of tabs is determined by the user in the real program) and then having each tab display results of each process in real time.
My hope is to have the user be able to start/stop a long process on each tab's data at will, and then be able to manually change the data in between starting/stopping the automated data manipulation process. I have tried making each tab have its own thread and then giving each thread its own process, which hasn't worked out very well but it may just be to me not understanding how to set it up.

Here is one of the simpler versions with only processes and one thread:

from PyQt4 import QtCore, QtGui
import multiprocessing as mp
import sys
import time

def make_data():
    data = {'num': 3, 'num2':4}
    return data

num = 1000000

def some_complex_processing(data, Event):
    for i in range(data['num'], data['num'] + num):
        if Event.isSet():
            Event.wait()
        else:
            data['num'] = i
            data['num2'] = i+100
    
class Tab(QtGui.QTabWidget):
    def __init__(self, parent, data_init):
        QtGui.QTabWidget.__init__(self, parent)
        self.top_level_layout = QtGui.QGridLayout(self)
        self.frame = QtGui.QFrame(self)
        self.top_level_layout.addWidget(self.frame)
        self.step_label = dict()
        self.step_stacked = dict()
        self.step_text = dict()
        self.step_input = dict()
        for wdgts in data_init.keys():
            self.step_label[wdgts] = QtGui.QLabel(str(wdgts))
            self.step_stacked[wdgts] = QtGui.QStackedWidget()
            self.step_text[wdgts] = QtGui.QLabel(str(data_init[wdgts]))
            self.step_input[wdgts] = QtGui.QLineEdit()
            self.step_stacked[wdgts].addWidget(self.step_text[wdgts])
            self.step_stacked[wdgts].addWidget(self.step_input[wdgts])
            self.top_level_layout.addWidget(self.step_stacked[wdgts])
            self.top_level_layout.addWidget(self.step_label[wdgts])
        
        self.process_button = QtGui.QPushButton("Process")
        self.top_level_layout.addWidget(self.process_button, 1, 1)
        self.process_button.clicked.connect(self.start_process)

        self.manager = mp.Manager()
        self.data = self.manager.dict(make_data())
        self.Event = self.manager.Event()
        self.process = mp.Process(target=some_complex_processing, args=(self.data,self.Event,))
        
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update_GUI)

    def update_GUI(self):
        try:
            for wdgt in self.data.keys():
                self.step_label[wdgt].setText(str(wdgt))
                self.step_text[wdgt].setText(str(self.data[wdgt]))
                self.step_input[wdgt].setText(str(self.data[wdgt]))
        except EOFError:
            QtCore.QObject.disconnect(self.process_button, QtCore.SIGNAL("clicked()"), self.stop_process)
            QtCore.QObject.disconnect(self.process_button, QtCore.SIGNAL("clicked()"), self.start_process)
            self.timer.stop()
            self.process.join()
##        except IOError:
##            pass
        return

    def start_process(self):
        for wdgt in self.step_stacked.keys():
            self.step_stacked[wdgt].setCurrentWidget(self.step_text[wdgt])
        try:
            self.process.start()
        except:
            self.Event.clear()
        self.timer.start()
        self.process_button.setText('Stop Processing - (manually adjust data)')
        QtCore.QObject.disconnect(self.process_button, QtCore.SIGNAL("clicked()"), self.start_process)
        QtCore.QObject.connect(self.process_button, QtCore.SIGNAL("clicked()"), self.stop_process)
        return

    def stop_process(self):
        self.Event.set()
        for wdgt in self.step_stacked.keys():
            self.step_stacked[wdgt].setCurrentWidget(self.step_input[wdgt])
        self.timer.stop()
        self.process_button.setText('Start Processing Again Using Data')
        QtCore.QObject.disconnect(self.process_button, QtCore.SIGNAL("clicked()"), self.stop_process)
        QtCore.QObject.connect(self.process_button, QtCore.SIGNAL("clicked()"), self.start_process)
        return
        
# GUI stuff
class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self)
        screen_height = app.desktop().screenGeometry().height()
        screen_width = app.desktop().screenGeometry().width()
        self.resize(int(screen_width*0.2), int(screen_height*0.2))
        self.tab_list = []
        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)
        self.setCentralWidget(self.centralwidget)
        self.centralwidget.setLayout(self.top_level_layout)
        self.process_all__button = QtGui.QPushButton("Start All Processes")
        self.top_level_layout.addWidget(self.process_all__button, 0, 0)
        QtCore.QObject.connect(self.process_all__button, QtCore.SIGNAL("clicked()"), self.start_all_process)
        # Make Tabs in loop from button
        for i in range(0,10):
            super_cool_data = make_data()
            name = 'tab ' + str(i)
            self.tab_list.append(Tab(self.tabWidget, super_cool_data))
            self.tabWidget.addTab(self.tab_list[-1], name)
            
    def start_all_process(self):
        self.process_all__button.setText('Stop All Processing')
        QtCore.QObject.disconnect(self.process_all__button, QtCore.SIGNAL("clicked()"), self.start_all_process)
        QtCore.QObject.connect(self.process_all__button, QtCore.SIGNAL("clicked()"), self.stop_all_process)
        for i in self.tab_list:
            i.start_process()
            
    def stop_all_process(self):
        self.process_all__button.setText('Start All Processing')
        QtCore.QObject.disconnect(self.process_all__button, QtCore.SIGNAL("clicked()"), self.stop_all_process)
        QtCore.QObject.connect(self.process_all__button, QtCore.SIGNAL("clicked()"), self.start_all_process)
        for i in self.tab_list:
            i.stop_process()        

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