A part of what I am doing, needs me to have background music
in a tkinter
game I created long time ago. I am using playsound.playsound
{ Docs Here } to play music . I could use any other tool if needed to achieve what I intend like pyglet.media
or pygame.mixer
.
As the actual program was about 1k lines, I have tried adding an MCVE below.
Desired behavior & issue
The BGM (Background Music) should start when the app is launched - of course alongside a GUI, I would have a button
to stop the BGM OR more preferably pause/play - I do think I need to use anything other than playsound.playsound
for pause/play behavior.
The issue:: I can't seem to figure out how to make that communication
between both the threads
so that I can stop the music from playing or perhaps terminate
the thread playing BGM - I could create a new thread when needed.
What I Have Tried
First up, I created two classes for GUI and BGM, each inheriting
from threading.Thread
- overridden the constructor
and run()
methods to do what I intend. Like this -
import tkinter as tk
import threading
from playsound import playsound
class BGM(threading.Thread):
def __init__(self, stopSignal):
threading.Thread.__init__(self)
self.stopSignal = stopSignal
def run(self):
while not self.stopSignal:
playsound('LoL.mp3') # to make this function play asynchronously, pass in False as second arg.
class GUI(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.root = tk.Tk()
def run(self):
tk.Button(self.root, text='stop').pack()
if __name__ == '__main__':
guiThread = GUI()
guiThread.start()
musicThread = BGM(0)
musicThread.start()
guiThread.root.mainloop()
But as you can see, it will just continue to play the song infinitely as long as the app is alive. There is no communication ( or active sync ) between GUI ( the button to stop song ) and BGM thread.
Now I tried using threading.Event()
objects. The official docs on threading.Event() quotes:
This is one of the simplest mechanisms for communication between threads: one thread signals an event and other threads wait for it.
An event object manages an internal flag that can be set to true with the set() method and reset to false with the clear() method. The wait() method blocks until the flag is true.
I'm not sure if this is useful for me to achieve what I intend but using threading.Event()
did not do anything for me (or maybe I wasn't able to make use of it properly)
Now
What would you suggest to do to implement a BGM thread which can be stopped ( or paused/played preferably ) with a button(s) in the GUI thread.
Thank You For Any help Or Suggestions :)