简体   繁体   中英

Run multiple qthreads concurrently in Python

In the attached code when you click start it creates a QSpinBox and starts counting to 20 in QThread , but if I click start again while it is counting, the first QSpinBox stops and a new one takes the focus, and both counters run in it, but I need all spins to run at the same time separately:

import sys
import time
from PySide.QtGui import *
from PySide.QtCore import *

class frmMain(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.btStart = QPushButton('Start')
        self.btStop = QPushButton('Stop')
        self.counter = QSpinBox()
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.btStart)
        self.layout.addWidget(self.btStop)
        self.layout.addWidget(self.counter)
        self.setLayout(self.layout)
        self.btStart.clicked.connect(self.start_thread)
        self.btStop.clicked.connect(self.stop_thread)
        self.boxes = []

    def stop_thread(self):
        self.th.stop()

    def loopfunction(self, x):
        self.boxes[-1].setValue(x)

    def start_thread(self):
        self.th = thread(2)
        self.th.loop.connect(self.loopfunction)
        self.th.setTerminationEnabled(True)
        self.boxes.append(QSpinBox())
        self.layout.addWidget(self.boxes[-1])
        self.th.start()

class thread(QThread):
    loop = Signal(object)

    def __init__(self, x):
        QThread.__init__(self)
        self.x = x

    def run(self):
        for i in range(20):
            self.x = i
            self.loop.emit(self.x)
            time.sleep(0.5)

    def stop(self):
        self.stop()


app = QApplication(sys.argv)
win = frmMain()

win.show()
sys.exit(app.exec_())

I made a few key changes:

  • kept a list of the separate threads as you were overwriting the same thread object,
  • fixed the recursive error when stopping a thread; used terminate instead,
  • thread keeps track of it's own index so it knows which spin box to update.

It's not really clear what you want to happen when you press stop, or press start after stopping, but this code should more or less work for you:

import sys
import time
from PySide.QtGui import *
from PySide.QtCore import *

class frmMain(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.btStart = QPushButton('Start')
        self.btStop = QPushButton('Stop')
        #self.counter = QSpinBox()
        self.layout = QVBoxLayout()
        self.layout.addWidget(self.btStart)
        self.layout.addWidget(self.btStop)
        #self.layout.addWidget(self.counter)
        self.setLayout(self.layout)
        self.btStart.clicked.connect(self.start_thread)
        self.btStop.clicked.connect(self.stop_thread)
        self.boxes = []
        self.threads = []

    def stop_thread(self):
        for th in self.threads:
            th.terminate()

    def loopfunction(self, n, index):
        self.boxes[index].setValue(n)

    def start_thread(self):
        index = len(self.threads)
        th = thread(index)
        th.loop.connect(self.loopfunction)
        th.setTerminationEnabled(True)
        th.start()
        self.threads.append(th)        
        self.boxes.append(QSpinBox())
        self.layout.addWidget(self.boxes[index])        


class thread(QThread):
    loop = Signal(int, int)

    def __init__(self, index):
        QThread.__init__(self)
        self.index = index

    def run(self):
        for n in range(20):
            self.loop.emit(n, self.index)
            time.sleep(0.5)


app = QApplication(sys.argv)
win = frmMain()

win.show()
sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM