Python 在播放wav文件时失去对GUI的控制

Python 在播放wav文件时失去对GUI的控制,python,Python,我不明白为什么我正在失去对GUI的控制,即使我正在实现一个线程来播放一个.wav文件。有人能指出什么是错误的吗 #!/usr/bin/env python import wx, pyaudio, wave, easygui, thread, time, os, sys, traceback, threading import wx.lib.delayedresult as inbg isPaused = False isStopped = False class Frame(wx.

我不明白为什么我正在失去对GUI的控制,即使我正在实现一个线程来播放一个.wav文件。有人能指出什么是错误的吗

    #!/usr/bin/env python

import wx, pyaudio, wave, easygui, thread, time, os, sys, traceback, threading
import wx.lib.delayedresult as inbg

isPaused = False
isStopped = False

class Frame(wx.Frame):
 def __init__(self):
            print 'Frame'
            wx.Frame.__init__(self, parent=None, id=-1, title="Jasmine", size=(720, 300))

            #initialize panel
            panel = wx.Panel(self, -1)

            #initialize grid bag
            sizer = wx.GridBagSizer(hgap=20, vgap=20) 

            #initialize buttons
            exitButton = wx.Button(panel, wx.ID_ANY, "Exit")
            pauseButton = wx.Button(panel, wx.ID_ANY, 'Pause')
            prevButton = wx.Button(panel, wx.ID_ANY, 'Prev')
            nextButton = wx.Button(panel, wx.ID_ANY, 'Next')
            stopButton = wx.Button(panel, wx.ID_ANY, 'Stop')

            #add widgets to sizer
            sizer.Add(pauseButton, pos=(1,10))
            sizer.Add(prevButton, pos=(1,11))
            sizer.Add(nextButton, pos=(1,12))
            sizer.Add(stopButton, pos=(1,13))
            sizer.Add(exitButton, pos=(5,13))

            #initialize song time gauge
            #timeGauge = wx.Gauge(panel, 20)
            #sizer.Add(timeGauge, pos=(3,10), span=(0, 0))

            #initialize menuFile widget
            menuFile = wx.Menu()
            menuFile.Append(0, "L&oad")
            menuFile.Append(1, "E&xit")
            menuBar = wx.MenuBar()
            menuBar.Append(menuFile, "&File")
            menuAbout = wx.Menu()
            menuAbout.Append(2, "A&bout...")
            menuAbout.AppendSeparator()
            menuBar.Append(menuAbout, "Help")
            self.SetMenuBar(menuBar)
            self.CreateStatusBar()
            self.SetStatusText("Welcome to Jasime!")

            #place sizer on panel
            panel.SetSizer(sizer)

            #initialize icon
            self.cd_image = wx.Image('cd_icon.png', wx.BITMAP_TYPE_PNG)
            self.temp = self.cd_image.ConvertToBitmap()
            self.size = self.temp.GetWidth(), self.temp.GetHeight()
            wx.StaticBitmap(parent=panel, bitmap=self.temp)

  #set binding
            self.Bind(wx.EVT_BUTTON, self.OnQuit, id=exitButton.GetId())
            self.Bind(wx.EVT_BUTTON, self.pause, id=pauseButton.GetId())
            self.Bind(wx.EVT_BUTTON, self.stop, id=stopButton.GetId())
            self.Bind(wx.EVT_MENU, self.loadFile, id=0)
            self.Bind(wx.EVT_MENU, self.OnQuit, id=1)  
            self.Bind(wx.EVT_MENU, self.OnAbout, id=2)

 #Load file using FileDialog, and create a thread for user control while running the file 
 def loadFile(self, event):

  foo = wx.FileDialog(self, message="Open a .wav file...", defaultDir=os.getcwd(), defaultFile="", style=wx.FD_MULTIPLE)
  foo.ShowModal()

  self.queue = foo.GetPaths()
  self.threadID = 1  

  while len(self.queue) != 0:
   self.song = myThread(self.threadID, self.queue[0])
   self.song.start()
   while self.song.isAlive():
    time.sleep(2)
   self.queue.pop(0)
                self.threadID += 1

 def OnQuit(self, event):
  self.Close()

 def OnAbout(self, event):
  wx.MessageBox("This is a great cup of tea.", "About Jasmine", wx.OK | wx.ICON_INFORMATION, self)

 def pause(self, event):
  global isPaused
  isPaused = not isPaused

 def stop(self, event):
  global isStopped
  isStopped = not isStopped


class myThread (threading.Thread):
  def __init__(self, threadID, wf):
   self.threadID = threadID
   self.wf = wf
   threading.Thread.__init__(self)
  def run(self):
   global isPaused
   global isStopped  

   self.waveFile = wave.open(self.wf, 'rb')         

   #initialize stream
   self.p = pyaudio.PyAudio()
   self.stream = self.p.open(format = self.p.get_format_from_width(self.waveFile.getsampwidth()), channels = self.waveFile.getnchannels(), rate = self.waveFile.getframerate(), output = True)
   self.data = self.waveFile.readframes(1024)

   isPaused = False
   isStopped = False
   #main play loop, with pause event checking
   while self.data != '':
   # while isPaused != True:
   #  if isStopped == False:
     self.stream.write(self.data)
     self.data = self.waveFile.readframes(1024)
   #  elif isStopped == True:
   #   self.stream.close()
   #   self.p.terminate()

   self.stream.close()
   self.p.terminate()

class App(wx.App):

 def OnInit(self):
  self.frame = Frame()
  self.frame.Show()
  self.SetTopWindow(self.frame)
  return True

def main():
 app = App()
 app.MainLoop()

if __name__=='__main__':
 main()

您的
loadFile
方法,完全独立于它将歌曲播放委托给多个线程(它以奇怪的方式等待,但这是另一个问题)的事实,仍然垄断wx事件循环,直到它返回。如果您当前有一个
时间。sleep
,请尝试添加
app.Yield(True)
(当然,您需要使
app
在代码中的该点可见:最简单但不雅观的方法是在
main
的开头添加一个
全局应用程序


事件驱动系统通常仅在您的各种事件处理程序方法返回时才为事件循环提供服务:如果您有一个长期运行的事件处理程序,您需要偶尔显式地将控制权让给事件循环。各种事件系统提供了不同的方法:在
wx
中,我只是重新推荐了
yield
方法如果您想尝试,请参阅下一次(甚至这次)的简要说明。

请创建一个简洁的代码示例,准确地再现您的问题。几乎每次您这样做,您最终都会自己解决问题。如果您不这样做,其他人会更容易提供帮助。我还建议您编写一个更具体的标题。