2010-06-17 3 views
-1

Je n'arrive pas à comprendre pourquoi je perds le contrôle de mon interface graphique, même si j'implémente un thread pour lire un fichier .wav. Quelqu'un peut-il pointer ce qui est incorrect?Perdre le contrôle de l'interface graphique lors de la lecture d'un fichier 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() 
+0

La prochaine fois (ou même cette fois) pl facilité créer un échantillon concis de code qui reproduit votre problème exactement. Presque chaque fois que vous faites cela, vous finirez par résoudre vous-même le problème. Si vous ne le faites pas, il est beaucoup plus facile pour quelqu'un d'autre de vous aider. –

+2

Je vous recommande également d'écrire un titre plus spécifique. –

Répondre

2

Votre méthode loadFile, indépendamment du fait qu'il délègue chanson à jouer à de nombreux fils (dont il attend de façon étrange, mais c'est une autre question), est encore monopolisant la boucle d'événements WX jusqu'à ce qu'il revienne. Où que vous avez actuellement un time.sleep, essayez d'ajouter app.Yield(True) (bien sûr, vous devez faire app visible à ce moment-là dans votre code. Plus simple si inélégant est d'ajouter un global app au début de main

systèmes Event-driven servent généralement la boucle d'événements uniquement lorsque vos différentes méthodes de gestionnaires d'événements renvoient: si vous avez un gestionnaire d'événements de longue durée, vous devez explicitement céder le contrôle à la boucle d'événement de temps en temps. c'est la méthode Yield que je viens de vous recommander d'essayer.Voir la brève description un the docs

Questions connexes