2010-06-17 53 views
-1

我无法理解为什么即使我正在实现一个线程来播放.wav文件,我失去了对GUI的控制权。有人可以指出什么是不正确的?在播放wav文件时失去对GUI的控制

#!/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() 
+0

下一次(甚至是这次)pl轻松创建一个简洁的代码示例,可以准确再现您的问题。几乎每次你这样做,你最终都会自己解决问题。如果你不这样做,这会让其他人更容易帮忙。 – 2010-06-17 00:30:26

+2

我也建议你写一个更具体的标题。 – 2010-06-17 01:09:11

回答

2

loadFile方法,完全独立的事实,它代表歌曲播放到许多线程(它等待以奇怪的方式,但是,这是另一个问题),是仍然垄断WX事件循环直到它返回。当您当前有time.sleep,尝试加入app.Yield(True)(当然,你需要在你的代码点,使app可见:最简单的,虽然不雅是在main开始添加global app

事件驱动系统通常服务事件循环只有当你的各种事件处理程序方法返回时:如果你有一个长时间运行的事件处理程序,你需要明确地控制事件循环一次,各种事件系统提供了不同的方式来做到这一点:在wx,这是Yield方法,我只是推荐你试试。查看简单说明un the docs