Getting back into programming after a 20 years hiatus. Been reading that the use of global variables in python is a sign of bad design, but can't figure out a better way of doing it.
Below is a small program that utilizes a global variable 'paused' to determine the state of the music player. This variable is utilized by a couple of functions.
Is there a better way of doing this without utilizing a global variable?
# Global variable to access from multiple functions
paused = False
def play_music():
    global paused
    if not paused:
        try:
            mixer.music.load(filename)
            mixer.music.play()
            statusBar['text'] = 'Playing Music - ' + os.path.basename(filename)
        except:
            tkinter.messagebox.showerror('File not found',
                                         'Melody could not find the file.')
    else:
        mixer.music.unpause()
        paused = False
        statusBar['text'] = 'Playing Music - ' + os.path.basename(filename)
def stop_music():
    mixer.music.stop()
    statusBar['text'] = 'Music stopped'
def pause_music():
    global paused
    if not paused:
        mixer.music.pause()
        paused = True
        statusBar['text'] = 'Music paused'
    else:
        play_music()
                You could put all your functions inside a class, and make the "global" variable an attribute. In that way you can share it between methods:
class Player(object):
    def __init__(self):
        self.paused = False
    def play_music(self):
        if not self.paused:
            # and so on
    def pause_music(self):
        if not self.paused:
            # etc.
                        In case anyone else is interested, below is the improved code where a Player class was created to encapsulate the pause variable:
import os
from tkinter import *
from tkinter import filedialog
import tkinter.messagebox
from pygame import mixer
# Global variable to access from multiple functions
# paused = False
class Player:
    def __init__(self):
        self.paused = False
        self.filename = None
    def play_music(self):
        if not self.paused:
            try:
                mixer.music.load(self.filename)
                mixer.music.play()
                statusBar['text'] = 'Playing Music - ' + os.path.basename(self.filename)
            except FileNotFoundError:
                tkinter.messagebox.showerror('File not found',
                                             'Melody could not find the file. Please choose a music file to play')
        else:
            mixer.music.unpause()
            self.paused = False
            statusBar['text'] = 'Playing Music - ' + os.path.basename(self.filename)
    @staticmethod
    def stop_music():
        mixer.music.stop()
        statusBar['text'] = 'Music stopped'
    def pause_music(self):
        if not self.paused:
            mixer.music.pause()
            self.paused = True
            statusBar['text'] = 'Music paused'
        else:
            self.play_music()
    def rewind_music(self):
        self.play_music()
        statusBar['text'] = 'Music rewound'
    @staticmethod
    def set_volume(val):
        # val is set automatically by the any tkinter widget
        volume = int(val)/100   # mixer only takes value between 0 and 1
        mixer.music.set_volume(volume)
    # Create about us Message Box
    @staticmethod
    def about_us():
        tkinter.messagebox.showinfo('About Melody', 'This is a music player built using python and tkinter')
    def browse_file(self):
        self.filename = filedialog.askopenfilename()
        print(self.filename)
# Create main window
root = Tk()
# Create window frames
middle_frame = Frame(root)
bottom_frame = Frame(root)
# Create Menu
menu_bar = Menu(root)
root.config(menu=menu_bar)
# Create Player object
player = Player()
subMenu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="File", menu=subMenu)
subMenu.add_command(label="Open", command=player.browse_file)
subMenu.add_command(label="Exit",  command=root.destroy)
# it appears we can re-use subMenu variable and re-assign it
subMenu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label="Help", menu=subMenu)
subMenu.add_command(label="About Us", command=player.about_us)
# Initialise Mixer
mixer.init()
# Create and set the main window
root.title("Melody")
root.wm_iconbitmap(r'favicon.ico')
# root.geometry('300x300')
# Create and arrange widgets
text = Label(root, text="Lets make some noise!")
text.pack(pady=10)
middle_frame.pack(pady=30, padx=30)   # Place the middle and bottom frame below this text
bottom_frame.pack()
playPhoto = PhotoImage(file='play-button.png')
playBtn = Button(middle_frame, image=playPhoto, command=player.play_music)
playBtn.grid(row=0, column=0, padx=10)
stopPhoto = PhotoImage(file='stop-button.png')
stopBtn = Button(middle_frame, image=stopPhoto, command=player.stop_music)
stopBtn.grid(row=0, column=1, padx=10)
pausePhoto = PhotoImage(file='pause-button.png')
pauseBtn = Button(middle_frame, image=pausePhoto, command=player.pause_music)
pauseBtn.grid(row=0, column=2, padx=10)
rewindPhoto = PhotoImage(file='rewind-button.png')
rewindBtn = Button(bottom_frame, image=rewindPhoto, command=player.rewind_music)
rewindBtn.grid(row=0, column=0, padx=20)
# Create and set volume slider
scale = Scale(bottom_frame, from_=0, to=100, orient=HORIZONTAL, command=player.set_volume)
scale.set(70)  # set default slider and and volume
player.set_volume(70)
scale.grid(row=0, column=1, padx=10)
statusBar = Label(root, text='Welcome to Melody', relief=SUNKEN, anchor=W)
statusBar.pack(side=BOTTOM, fill=X)
# Keep main window displayed
root.mainloop()
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With