2012-04-23 114 views
4

我想创造一个游戏一个简单的GUI和停止按钮在python播放MP3文件。我使用Tkinter创建了一个非常简单的gui,它由2个按钮组成(停止和播放)。玩Pyglet和Tkinter的音乐在Python

我创建了一个函数,执行以下操作:

def playsound() : 
    sound = pyglet.media.load('music.mp3') 
    sound.play() 
    pyglet.app.run() 

我添加了功能的按钮播放的命令。我也做了不同的功能停止的音乐:

def stopsound(): 
    pyglet.app.exit 

我添加了这个功能的第二个按钮的命令。但问题是,当我玩游戏时,python和gui会冻结。我可以尝试关闭窗口,但它没有关闭,停止按钮没有响应。我知道这是因为pyglet.app.run()正在执行,直到歌曲结束,但我怎样才能防止这种情况?当我点击按钮时,我想让gui停止音乐。我可以在哪里找到解决方案的任何想法?

回答

4

你是混合两种UI库一起 - 这本质上并不坏,但也有一些问题。值得注意的是,他们都需要自己的主循环来处理他们的事件。 TKinter使用它来与桌面和用户生成的事件进行通信,在这种情况下,pyglet使用它来播放您的音乐。

这些循环中的每一个防止正常的“自上而下”的程序流程,因为我们习惯了当我们学会非GUI编程,程序应该从主回路回调基本上进行。在这种情况下,在Tkinter的回调中,你把pyglet主循环(调用pyglet.app.run)的运动,控制永远不会返回到Tkinter的图书馆。

有时循环不同的库都可以在同一个进程中共存,不会发生冲突 - 但你当然会处于运行其中的一个或另一个。如果是这样,可以在不同的Python线程中运行每个库的主循环。

如果他们不能同时存在,你将不得不应对一个不同的过程每个库。

所以,让音乐播放器一个办法在另一个线程开始可能是:

from threading import Thread 

def real_playsound() : 
    sound = pyglet.media.load('music.mp3') 
    sound.play() 
    pyglet.app.run() 

def playsound(): 
    global player_thread 
    player_thread = Thread(target=real_playsound) 
    player_thread.start() 

如果Tkinter的和pyglet是可以共存的,这应该是足以让你的音乐开始。 但是,为了能够控制它,你需要实现更多的东西。我的建议是有pyglet线由pyglet每秒或所谓的回调 - 这个回调检查一些全局变量的状态,并根据他们选择停止音乐,更改文件正在播放,等等上。

+0

嗨好,我有一个更好的了解。我该如何在pyglet上进行回调。根据我的基本理解,你所建议的有一个全局变量,只要按下某个按钮就会将其设置为某个值。如果按下停止按钮,则值被更改并且pyglet实例需要停止。我明白这是如何实现的,但是如何确保pyglet线程检查每秒是否这个全局变量是否是正确的值? – Paul 2012-04-24 00:23:02

1

我会做这样的事情:

import pyglet 
from pyglet.gl import * 

class main (pyglet.window.Window): 
    def __init__ (self): 
     super(main, self).__init__(800, 600, fullscreen = False) 
     self.button_texture = pyglet.image.load('button.png') 
     self.button = pyglet.sprite.Sprite(self.button_texture) 

     self.sound = pyglet.media.load('music.mp3') 
     self.sound.play() 

     self.alive = 1 

    def on_draw(self): 
     self.render() 

    def on_close(self): 
     self.alive = 0 

    def on_mouse_press(self, x, y, button, modifiers): 
     if x > self.button.x and x < (self.button.x + self.button_texture.width): 
      if y > self.button.y and y < (self.button.y + self.button_texture.height): 
       self.alive = 0 

    def on_key_press(self, symbol, modifiers): 
     if symbol == 65307: # [ESC] 
      self.alive = 0 

    def render(self): 
     self.clear() 
     self.button.draw() 
     self.flip() 

    def run(self): 
     while self.alive == 1: 
      self.render() 

      # -----------> This is key <---------- 
      # This is what replaces pyglet.app.run() 
      # but is required for the GUI to not freeze 
      # 
      event = self.dispatch_events() 


x = main() 
x.run() 
1

这个解决方案是最简单的一个:

import pyglet 
foo=pyglet.media.load("/data/Me/Music/Goo Goo Dolls/[1998] Dizzy Up The Girl/11 - Iris.mp3") 
foo.play() 

def exiter(dt): 
    pyglet.app.exit() 
print "Song length is: %f" % foo.duration 
# foo.duration is the song length 
pyglet.clock.schedule_once(exiter, foo.duration) 

pyglet.app.run() 

来源:http://ubuntuforums.org/showthread.php?t=1651906