使用PyQt4线程时仍然冻结

时间:2015-05-16 20:24:19

标签: multithreading pyqt midi

尽管使用了QThread,但GUI仍处于冻结状态

(代码贴在最后) 空格键被点击,通过创建线程并向播放功能发出调用来开始播放midi音符

if self.playing is False:
    # PlayThread is initiated in PianoRoll when the space bar is hit. 
    Loop iterates and plays data, freezing the GUI

else:
    # This section is not reached because another space bar hit cannot be received while data is looping

我已经在StackOverflow上查看了以下教程和各种响应:

  1. https://manojbits.wordpress.com/2013/01/24/threading-in-pyqt4/
  2. joplaete教程
  3. 我尝试过以下方法:

    1. 将所有循环代码置于已发出信号的函数
    2. 将循环放在线程的运行函数中,并使用emit
    3. 将数据传递给信号函数
    4. 将函数与处理对其调用的窗口小部件分开
    5. 使数据结构全局化(尝试任何事情)
    6. 请告诉我我缺少的内容或是否需要其他代码。

      我使用的是开源MIDI音序器模板     https://github.com/rhetr/seq-gui

      class PlayThread(QtCore.QThread):
      
          def __init__(self):
      
              # qtcore.QThread.__init__(self, parent=app)
      
              super(PlayThread , self).__init__()
      
              self.signal = QtCore.SIGNAL("signal")
      
          def run(self):
      
              global xLocToNoteItems
      
              # this loop was attempted in the signaled function as well
              for xloc in xLocToNoteItems:
      
                  self.emit(self.signal, xloc)
      
              # self.emit(self.signal, "arbitrary?")
      
              # self.emit(QtCore.SIGNAL('update(QString)') + str(i))
      
      钢琴卷

      if event.key() == QtCore.Qt.Key_Space:
      
          if self.playing:
      
              self.playing = False
      
              # terminate play thread
      
              main.playThread.quit()
      
          else:
      
              self.playing = True
      
              # playThread previously attempted to be stored in this (piano roll) class
                  # ...was moved to main in case the call was freezing the piano roll
              main.playThread = PlayThread()
      
          main.connect(main.playThread, main.playThread.signal, main.play)
      
          main.playThread.start()
      

      播放功能位于钢琴卷小部件中,现在位于主

      def play(self, xloc):
      
          # for xloc in main.xLocToNoteItems:
      
      
          global xLocToRhythms
          global xLocToNoteItems
      
          for noteItem in xLocToNoteItems[xloc]:
      
              player.note_on(noteItem.note[0], noteItem.note[3], 1)
      
          offtime = xLocToRhythms[xloc]
      
          time.sleep(offtime)
      
          for noteItem in xLocToNoteItems[xloc]:
      
              player.note_off(noteItem.note[0], noteItem.note[3], 1)
      

1 个答案:

答案 0 :(得分:1)

你的线程故意发出多个信号来执行主线程中的play()方法。您的play方法必须运行一段合理的时间并阻塞主线程(例如它中有一个time.sleep)。

您可能还需要将play代码移动到线程中,但前提是您正在使用的MIDI库可以安全地从辅助线程调用。请注意,如果您计划从多个线程调用库,则还应检查库是否是线程安全的。