title: QPixmap: It is not safe to use pixmaps outside the GUI thread
body: <p>I am using PySide to make a GUI application. I have 3 classes: A QWidget class, a QThread Worker class and a controller for the Worker class. The GUI class creates a controller object that spawns a given number of worker threads, in that hierarchy:</p>
  <pre><code>class Worker(QtCore.QThread):
      # Signal that tells the controller the current progress of the
      # thread.
      sig_worker_update_progress = QtCore.Signal(int, int)
  
      def __init__(self, thread_id, *args, **kwargs):
          super(Worker, self).__init__(*args, **kwargs)
          self.thread_id = thread_id
  
      def run(self):
          # Enter
          # Loop
          self.sig_worker_update_progress.emit(self.thread_id, progress)
          # Continue
          # Loop
  
  class Controller(QtCore.QObject):
      sig_controller_update_progress = QtCore.Signal(int, int)
  
      def __init__(self, num_workers, *args, **kwargs):
          super(Controller, self).__init__(*args, **kwargs)
          
          self.workers = []
          for i in range(num_workers):
              self.workers.append(Worker(i))
              self.workers[i].sig_worker_update_progress.connect(
                  self.slot_worker_update_progress)
          for worker in self.workers:
              worker.start() 
  
      def slot_worker_update_progress(self, thread_id, progress):
          # Do
          # Stuff
          self.sig_controller_update_progress.emit(thread_id, progress)
  
  
  class Monitor(QtGui.QWidget):
      def __init__(self, num_workers, *args, **kwargs):
          super(Monitor, self).__init__(*args, **kwargs)
          main_layout = QtGui.QVBoxLayout()
          self.setLayout(main_layout)
          self.progress_bars = []
  
          for _ in range(num_workers):
              progress_bar = QtGui.QProgressBar()
              main_layout.addWidget(progress_bar)
              self.progress_bars.append(progress_bar)
  
          self.controller = Controller(num_workers)
          self.controller.sig_controller_update_progress.connect(
              self.slot_controller_update_progress)
  
      def slot_controller_update_progress(self, thread_id, progress):
          self.progress_bars[thread_id].setValue(progress)
  </code></pre>
  <p>Note that the connect calls appearing above use <code>QtCore.Qt.AutoConnection</code> as the <code>type</code> of connection (the default, since the keyword argument is not specified). Absent from the code above is functionality that causes the threads to exit when the user clicks a button on the widget, and other functionality that creates new threads when another button is clicked.</p>
  <p>When the interrupt button is clicked, I noticed that some items remain in the emit queue of both <code>Signal</code>s. This was unexpected, but I found out that this is standard behavior for Qt, since <a href="http://qt-project.org/doc/qt-4.8/qt.html#ConnectionType-enum" rel="nofollow noreferrer">the connections are queued by default</a>. I did not want anything to remain in the queue, so I decided to used a <code>DirectConnection</code> for both connections. When I did this, my application would run for a few seconds, then crash with the following output:</p>
  <blockquote>
  <p>QPixmap: It is not safe to use pixmaps outside the GUI thread</p>
  <p>QPixmap: It is not safe to use pixmaps outside the GUI thread</p>
  <p>QPainter::begin: Paint device returned engine == 0, type: 2</p>
  <p>QPainter::end: Painter not active, aborted</p>
  <p>Segmentation fault (core dumped)</p>
  </blockquote>
  <p>I researched the error. Apparently, <a href="https://stackoverflow.com/questions/5187608/i-am-not-using-qpixmap-in-pyqt-but-i-get-qpixmap-it-is-not-safe-to-use-pixmap">threads are not allowed to handle GUI objects directly</a>. The recommended approach is exactly what I have done: to use signals and slots.</p>
  <p>Even more curious is the fact that if I use an <code>AutoConnection</code> for either one of the connections and a <code>DirectConnection</code> for the other, the application runs fine (save for the residual emit items that confuse my final output).</p>
  <p>I need enlightenment from someone more experienced in Qt about what could be happening here.</p>