title: PyQt5 QThread not working, gui still freezing
body: <p>I have this code (if you have pyqt5, you should be able to run it yourself):</p>
  
  <pre><code>import sys
  import time
  
  from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget
  from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
  
  
  class Worker(QObject):
      def __init__(self):
          super().__init__()
          self.thread = None
  
  
  class Tab(QObject):
      def __init__(self, _main):
          super().__init__()
          self._main = _main
  
  
  class WorkerOne(Worker):
      finished = pyqtSignal()
  
      def __init__(self):
          super().__init__()
  
      @pyqtSlot(str)
      def print_name(self, name):
          for _ in range(100):
              print("Hello there, {0}!".format(name))
              time.sleep(1)
  
          self.finished.emit()
          self.thread.quit()
  
  
  class SomeTabController(Tab):
      def __init__(self, _main):
          super().__init__(_main)
          self.threads = {}
  
          self._main.button_start_thread.clicked.connect(self.start_thread)
  
          # Workers
          self.worker1 = WorkerOne()
          #self.worker2 = WorkerTwo()
          #self.worker3 = WorkerThree()
          #self.worker4 = WorkerFour()
  
      def _threaded_call(self, worker, fn, *args, signals=None, slots=None):
          thread = QThread()
          thread.setObjectName('thread_' + worker.__class__.__name__)
  
          # store because garbage collection
          self.threads[worker] = thread
  
          # give worker thread so it can be quit()
          worker.thread = thread
  
          # objects stay on threads after thread.quit()
          # need to move back to main thread to recycle the same Worker.
          # Error is thrown about Worker having thread (0x0) if you don't do this
          worker.moveToThread(QThread.currentThread())
  
          # move to newly created thread
          worker.moveToThread(thread)
  
          # Can now apply cross-thread signals/slots
  
          #worker.signals.connect(self.slots)
          if signals:
              for signal, slot in signals.items():
                  try:
                      signal.disconnect()
                  except TypeError:  # Signal has no slots to disconnect
                      pass
                  signal.connect(slot)
  
          #self.signals.connect(worker.slots)
          if slots:
              for slot, signal in slots.items():
                  try:
                      signal.disconnect()
                  except TypeError:  # Signal has no slots to disconnect
                      pass
                  signal.connect(slot)
  
          thread.started.connect(lambda: fn(*args)) # fn needs to be slot
          thread.start()
  
      @pyqtSlot()
      def _receive_signal(self):
          print("Signal received.")
  
      @pyqtSlot(bool)
      def start_thread(self):
          name = "Bob"
          signals = {self.worker1.finished: self._receive_signal}
          self._threaded_call(self.worker1, self.worker1.print_name, name,
                              signals=signals)
  
  
  class MainWindow(QWidget):
      def __init__(self):
          super().__init__()
  
          self.setWindowTitle("Thread Example")
          form_layout = QVBoxLayout()
          self.setLayout(form_layout)
          self.resize(400, 400)
  
          self.button_start_thread = QPushButton()
          self.button_start_thread.setText("Start thread.")
          form_layout.addWidget(self.button_start_thread)
  
          self.controller = SomeTabController(self)
  
  
  if __name__ == '__main__':
      app = QApplication(sys.argv)
  
      _main = MainWindow()
      _main.show()
  
      sys.exit(app.exec_())
  </code></pre>
  
  <p>However <code>WorkerOne</code> still blocks my GUI thread and the window is non-responsive when <code>WorkerOne.print_name</code> is running.</p>
  
  <p>I have been researching a lot about QThreads recently and I am not sure why this isn't working based on the research I've done.</p>
  
  <p>What gives? </p>