5

Pythonでmp3ファイルを再生するための再生ボタンと停止ボタンを備えたシンプルなGUIを作成したかったのです。Tkinter を使用して、2 つのボタン (停止と再生) で構成される非常に単純な GUI を作成しました。

次のことを行う関数を作成しました。

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

その機能をボタン再生のコマンドとして追加しました。音楽を停止する別の関数も作成しました。

def stopsound ():
    pyglet.app.exit

この機能をコマンドとして 2 番目のボタンに追加しました。しかし、問題は、再生を押すと、python と gui がフリーズすることです。ウィンドウを閉じようとしても閉じず、停止ボタンも反応しません。これは、歌が終わるまで pyglet.app.run() が実行されているためだと理解していますが、どうすればこれを防ぐことができますか? ボタンをクリックすると、GUIが音楽を停止するようにします。これに対する解決策をどこで見つけることができるかについてのアイデアはありますか?

4

4 に答える 4

4

2 つの UI ライブラリを混在させています。これは本質的に悪いことではありませんが、いくつかの問題があります。特に、どちらもイベントを処理するために独自のメイン ループが必要です。TKinter はそれを使用してデスクトップおよびユーザー生成イベントと通信します。この場合、pyglet はそれを使用して音楽を再生します。

これらの各ループは、非 GUI プログラミングを学ぶときに慣れている通常の「トップダウン」プログラム フローを妨げ、プログラムは基本的にメイン ループからのコールバックを使用して続行する必要があります。この場合、Tkinter コールバックの途中で、pyglet のメインループ ( を呼び出しているpyglet.app.run) を起動し、制御が Tkinter ライブラリに戻ることはありません。

異なるライブラリのループが競合することなく同じプロセスに共存できる場合もありますが、もちろん、どちらか一方を実行することになります。その場合、各ライブラリのメインループを異なる Python スレッドで実行できる可能性があります。

それらが一緒に存在できない場合は、別のプロセスで各ライブラリを処理する必要があります。

したがって、音楽プレーヤーを別のスレッドで開始する方法の 1 つは、次のようになります。

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 によって約 1 秒ごとに呼び出される pyglet スレッドにコールバックを設定することです。このコールバックは、いくつかのグローバル変数の状態をチェックし、それらに基づいて、音楽の停止、再生中のファイルの変更などを選択します。の上。

于 2012-04-23T17:57:42.200 に答える
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()
于 2013-02-06T17:32:29.413 に答える
0

pyglet のドキュメントにメディア プレーヤーの実装があります。

http://www.pyglet.org/doc/programming_guide/playing_sounds_and_music.html

見るべきスクリプトはmedia_player.py です

うまくいけば、これで始めることができます

于 2012-04-23T15:28:45.917 に答える