使用 PyQt4 线程时仍然冻结
Still Freezing when using PyQt4 Thread
尽管使用了 QThread,GUI 仍然冻结
(代码贴在最后)
space 栏被击中,它通过创建线程并发出对播放函数的调用来开始播放 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
我查看了以下教程和 Whosebug 上的各种回复:
我试过以下方法:
- 将所有循环代码放在信号函数运行中
- 将循环放在线程的 运行 函数中,并使用 emit
将数据传递给有信号的函数
- 将函数与处理对它的调用的小部件分开
- 使数据结构全局化(尝试任何方法)
请让我知道我遗漏了什么或者是否需要任何其他代码。
我正在使用开源 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)
您的线程故意发出多个信号来执行主线程中的 play()
方法。您的 play
方法必须 运行 一段合理的时间并阻塞主线程(例如它有一个 time.sleep
)。
您可能还需要将 play
代码移动到线程中,但前提是您使用的 MIDI 库可以安全地从辅助线程调用。请注意,如果您打算从多个线程调用该库,您还应该检查该库是否是线程安全的。
尽管使用了 QThread,GUI 仍然冻结
(代码贴在最后) space 栏被击中,它通过创建线程并发出对播放函数的调用来开始播放 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
我查看了以下教程和 Whosebug 上的各种回复:
我试过以下方法:
- 将所有循环代码放在信号函数运行中
- 将循环放在线程的 运行 函数中,并使用 emit 将数据传递给有信号的函数
- 将函数与处理对它的调用的小部件分开
- 使数据结构全局化(尝试任何方法)
请让我知道我遗漏了什么或者是否需要任何其他代码。
我正在使用开源 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)
您的线程故意发出多个信号来执行主线程中的 play()
方法。您的 play
方法必须 运行 一段合理的时间并阻塞主线程(例如它有一个 time.sleep
)。
您可能还需要将 play
代码移动到线程中,但前提是您使用的 MIDI 库可以安全地从辅助线程调用。请注意,如果您打算从多个线程调用该库,您还应该检查该库是否是线程安全的。