0

I was looking to implement QRunnable and QThreadPool into my Qt application, where I want to have the GUI continuously listen in the background for microphone input. I have the thread working and it does run, however whenever I try to interact with the GUI the program crashes.

import vtk, qt, ctk, slicer
from slicer.ScriptedLoadableModule import *

class Worker(qt.QRunnable): 

  def widget(self, m, r): 
    self.m = m
    self.r = r

  def run(self): 

    with self.m as source:
      while True: 
        print("listening")
        self.r.adjust_for_ambient_noise(source)
        audio = self.r.listen(source)
        try: 
          print(self.r.recognize_google(audio))
        # handles any api/voice errors  errors 
        except sr.RequestError: 
          print("There was an issue in handling the request, please try again")
        except sr.UnknownValueError:
          print("Unable to Recognize speech")

class VoiceRecognitionWidget(ScriptedLoadableModuleWidget):
    def setup(self):
         ScriptedLoadableModuleWidget.setup(self)

         #Initializes recognizer and microphone 
         self.recognizer = sr.Recognizer()
         try: 
             self.microphone = sr.Microphone()

         except(IOError):
             print("ERROR: No default microphone. Check if microphone is plugged in or if you have a default microphone set in your sound settings.")
             self.errors.setText("ERROR: No default microphone. Check if your microphone is plugged in or if you have a default microphone set in your sound settings.")

         parametersCollapsibleButton = ctk.ctkCollapsibleButton()
         parametersCollapsibleButton.text = "Parameters"
         self.layout.addWidget(parametersCollapsibleButton)

         # Layout within the dummy collapsible button
         parametersFormLayout = qt.QFormLayout(parametersCollapsibleButton)


         self.listenButton = qt.QPushButton("Begin Listneing")
         self.listenButton.toolTip = "Listens for voice."
         self.listenButton.enabled = True
         parametersFormLayout.addRow(self.listenButton)


         self.stopButton = qt.QPushButton("Stop Listensing")
         self.stopButton.toolTip = "Stops listening."
         self.stopButton.enabled = True
         parametersFormLayout.addRow(self.stopButton)


         self.repeatButton = qt.QPushButton("Repeat last command")
         self.repeatButton.toolTip = "Listens for voice."
         self.repeatButton.enabled = True
         parametersFormLayout.addRow(self.repeatButton)

         self.listenButton.connect('clicked(bool)', self.onListenButton)
         self.stopButton.connect('clicked(bool)', self.onStopButton)
         self.repeatButton.connect('clicked(bool)', self.onRepeatButton)

    def onRepeatButton(self):
        self.logic.parse("repeat")

    def onStopButton(self): 
        self.stop_listening = True 


    def onListenButton(self):
        slicer.util.delayDisplay("Wait...", 2450)
        self.worker = Worker() 
        self.worker.widget(self.microphone, self.recognizer)
        #self.worker.start() #Q Thread method
        qt.QThreadPool.globalInstance().start(self.worker)

The listening loop does work. It picks up audio and it parses it well. Its just that whenever I do anything with the GUI, even if the button doesn't do anything, the program just crashes. No errors are shown as well. Any help would be massively appreciated. I'm writing a python module for the program 3DSlicer, thus the structure may look slightly different.

Steve Li
  • 53
  • 2
  • 10
  • 1
    Only main thread can modify GUI. Use Signal/Slots to update GUI from another thread. – Phiber Jul 31 '18 at 18:57
  • @Phiber Does pressing buttons count as modifying the GUI? Even when a button is connected to a slot that simply prints out something in the console the program crashes when it is pressed. – Steve Li Jul 31 '18 at 19:35
  • -> yes, in general, only main thread can interact with gui ( update, modify, touch, change, ...) – Phiber Jul 31 '18 at 22:27
  • Sorry I'm just a little confused. The QRunnable thread I made I thought doesn't interact with the gui at all, it just listens for voice in the microphone. – Steve Li Aug 01 '18 at 12:46
  • @SteveLi provide a [mcve] – eyllanesc Aug 01 '18 at 13:43

0 Answers0