开发者

Losing control of GUI upon playing a wav file

I can't understand why I am loosing control of my GUI even though I am implementing a thread to play a .wav file. Can someone pin point what is incorrect?

    #!/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()
     开发者_StackOverflow中文版       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()


Your loadFile method, quite independently of the fact that it delegates song-playing to many threads (which it waits for in strange ways, but, that's another issue), is still monopolizing the wx event loop until it returns. Where you currently have a time.sleep, try adding app.Yield(True) (of course you need to make app visible at that point in your code: simplest though inelegant is to add a global app at the start of main.

Event-driven systems typically serve the event loop only when your various event handler methods return: if you have a long-running event handler, you need to explicitly yield control to the event loop once in a while. Various event systems offer different ways to do it: in wx, it's the Yield method which I just recommended you try. See the brief description un the docs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜