Reputation: 1007
So I have been trying to create a GUI which works on multiple threads to perform each operation. Each operation actually has loops running on it and so I decided to use threads to run each operation simultaneously.
Here's some piece of code which describes the work flow.
Below there's a function called cvfeed1 which starts a thread when a button is pressed on the GUI using ( self.pushButton_3.clicked.connect(self.cvfeed1) ). When the threads starts it calls a function called colour_detect. The problem that I am facing is that I can only use this thread once, i.e I can only click the button once. When the operation in the functions is finished and I click the button again, the program crashes. What do I need to do to again make the thread work?
class MyWindowClass(QMainWindow, form_class):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setupUi(self)
self.startButton.clicked.connect(self.start_clicked)
self.pushButton.clicked.connect(self.printer)
# Here is the command when the button is clicked.
self.pushButton_3.clicked.connect(self.cvfeed1)
self.window_width = self.ImgWidget.frameSize().width()
self.window_height = self.ImgWidget.frameSize().height()
self.ImgWidget = OwnImageWidget(self.ImgWidget)
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.update_frame)
self.timer.start(1)
# This function starts the detect_1_thread
def cvfeed1(self):
detect_1_thread.start()
#self.pushButton_3.setEnabled(False)
def printer(self):
global running1
running1=True
printer_thread.start()
def start_clicked(self):
global running
running = True
capture_thread.start()
self.startButton.setEnabled(False)
self.startButton.setText('Starting...')
def update_frame(self):
if not q.empty():
self.startButton.setText('Camera is live')
frame = q.get()
img = frame["img"]
img_height, img_width, img_colors = img.shape
scale_w = float(self.window_width) / float(img_width)
scale_h = float(self.window_height) / float(img_height)
scale = min([scale_w, scale_h])
if scale == 0:
scale = 1
img = cv2.resize(img, None, fx=scale, fy=scale, interpolation = cv2.INTER_CUBIC)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
height, width, bpc = img.shape
bpl = bpc * width
image = QtGui.QImage(img.data, width, height, bpl, QtGui.QImage.Format_RGB888)
self.ImgWidget.setImage(image)
def closeEvent(self, event):
global running
running = False
capture_thread = threading.Thread(target=grab, args = (0, q, 1920, 1080, 30))
printer_thread = threading.Thread(target=printx)
detect_1_thread=threading.Thread(target=colour_detect)
app = QApplication(sys.argv)
w = MyWindowClass(None)
w.setWindowTitle('GUI')
w.show()
app.exec_()
Upvotes: 1
Views: 159
Reputation: 39818
You can’t start a thread more than once: it’s an action, not a machine that can be (re)used by another agent. You could start another thread using the same function, but without synchronization with the first thread you could end up with two running at once, which is probably a bad thing.
If you’re going to synchronize, you might as well keep the one thread running indefinitely and just post requests for it to process on some appropriate schedule. That schedule might allow preempting the current operation, or might allow only one request queued behind the current one, or whatever else.
Upvotes: 1