1

I'm trying to understand how thread works, and i'm stuck with this problem. That's my program explained: i made a simple GUI in pyqt that use a QObject as a worker class. When i press the botton start the gui read a random value from a list and pass it to the thread, that print the next five number. When the thread finish the work, it pass the data to the gui. Now i want the GUI to restart automatically a new thread with a new start value. I can restart the thread by pressing start again, but i need to start it without human interaction. Are there any method?

thanks in advance

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import time
import sys
import numpy as np



class SomeObject(QObject):

    finished = pyqtSignal(object)
    valore = pyqtSignal(object)
    vector = pyqtSignal(object)

    def __init():
        super(SomeObject, self).__init__()

    def longRunning(self):
        vec = []
        end = self.count + 5 
        while self.count < end:
            time.sleep(1)
            vec.append(self.count)
            self.valore.emit(self.count)
            self.count += 1
        self.finished.emit(vec)
        #self.vector.emit()

    def setCount(self, num):
        self.count = num

class GUI(QDialog):

    def __init__(self, parent = None):
        super(GUI, self).__init__(parent)
        #declare QThread object
        self.objThread = QThread()
        #declare SomeObject type, and move it to thread
        self.obj = SomeObject() 
        self.obj.moveToThread(self.objThread) 
        #connect finished signal to nextVector method
        self.obj.finished.connect(self.nextVector)
        #connect valore to self.prova method
        self.obj.valore.connect(self.prova)
        #self.obj.vector.connect(self.nextVector)
        #Connect thread.start to the method long running
        self.objThread.started.connect(self.obj.longRunning)

        botton = QPushButton("start")
        self.connect(botton, SIGNAL("clicked()"), self.showcount)
        box = QHBoxLayout()
        box.addWidget(botton)        
        self.setLayout(box)

        #a list of random number
        a = np.random.randint(10, size = 5)
        self.iter = iter(a)

    def showcount(self):
        """
        When botton clicked, read the next value from iter, pass it to
        setCount and when start the thread
        """        
        try:
            a = self.iter.next()
            print a
            self.obj.setCount(a)        
            self.objThread.start()
        except StopIteration:
            print "finito"
        #self.obj.setCount(a)        
        #self.objThread.start()
        #print self.objThread.currentThreadId()

    def prova(self, value):
        """
        Connected to signal valore, print the value
        """
        print value

    def nextVector(self, vec):
        """
        Print the whole vector
        """
        print vec
        self.objThread.quit()
        try:
            a = self.iter.next()
            print a
            self.obj.setCount(a)        
            self.objThread.start()
        except StopIteration:
            print "finito"

app = QApplication(sys.argv)
form = GUI()
form.show()
app.exec_()    
GiovanniPi
  • 260
  • 1
  • 8

1 Answers1

1

You already have it set up. When your thread is finished it emits the finished signal which calls the nextVector method, so just call the start method at the end of nextVector.

def nextVector(self, vec):
    ...
    self.showcount()
# end nextVector

You may also want to change to the new signal connection for your QPushButton

button.clicked.connect(self.showcount)
justengel
  • 6,132
  • 4
  • 26
  • 42
  • I tried it, but when the thread emit the finish signal the program recall the showcount method nothing happen. I find a solution by replacing self.obj.finished.connect(self.nextVector) with self.obj.finished.connect(self.objThread.quit) and self.objThread.finished.connect(self.nextVector), but honestly i don't get the difference – GiovanniPi Jul 15 '14 at 12:38
  • Oh well, another thing I should add is that a thread can only call a run method once then you should call the join method to free up that thread. if you want to run it multiple times you will have to recreate the thread again. Sorry, I thought you were creating a new thread each time in your showcount method. The only other way around this is a pausable thread class with locking. http://stackoverflow.com/questions/8103847/pausing-two-python-threads-while-a-third-one-does-stuff-with-locks – justengel Jul 15 '14 at 12:44
  • So the problem is that i'm trying to reuse a thread, instead making a new one, correct? The link you posted is interesting, but i prefer to use the QObject/Qthread method – GiovanniPi Jul 15 '14 at 13:38
  • Yes, a thread should only be used once. I prefer the python threading, because it forces this and throws an error if you try to start the thread a second time. http://stackoverflow.com/questions/14293368/restarting-thread-in-python-why-needs-the-instance-to-be-recreated – justengel Jul 15 '14 at 13:51