3、自定义窗口小部件
仅仅播放一首歌曲并控制音量时,我们完全可用hfmix1.pyw实现
代码如下:
from tkinter import *
import pygame.mixer
app = Tk()
app.title("Head First Mix")
sound_file = "1.WAV"
mixer = pygame.mixer
mixer.init()
def track_toggle():
if track_playing.get() == 1:
track.play(loops = -1)
else:
track.stop()
def change_volume(v):
track.set_volume(volume.get())
track = mixer.Sound(sound_file)
track_playing = IntVar()
track_button = Checkbutton(app,variable = track_playing,command = track_toggle,text = sound_file)
track_button.pack(side = 'left')
volume = DoubleVar()
volume.set(track.get_volume())
volume_scale = Scale(variable = volume,from_ = 0.0,to = 2.0,resolution = 0.1,command = change_volume,label = "Volume",orient = HORIZONTAL)
volume_scale.pack(side = 'right')
def shutdown():
track.stop()
app.destroy()
app.protocol("WM_DELETE_WINDOW",shutdown)
app.mainloop()
但如果要播放多首歌曲呢?当然可以多次拷贝粘贴,只不过这是一个很糟糕的想法。因为一旦需要修改每首歌的播放方式,就会产生各样的问题。应该重用代码,而不是复制。
这里,我们使用一种方式:创建函数——create_gui(),并将它放在sound_panel.py的独立模块作为开始。允许局部函数
sound_panel.py代码如下:
from tkinter import *
import pygame
def creat_gui(app,mixer,sound_file):
def track_toggle():
if track_playing.get() == 1:
track.play(loops = -1)
else:
track.stop()
def change_volume(v):
track.set_volume(volume.get())
track = mixer.Sound(sound_file)
track_playing = IntVar()
track_button = Checkbutton(app,variable = track_playing,command = track_toggle,text = sound_file)
track_button.pack(side = 'left')
volume = DoubleVar()
volume.set(track.get_volume())
volume_scale = Scale(variable = volume,from_ = 0.0,to = 2.0,resolution = 0.1,command = change_volume,label = "Volume",orient = HORIZONTAL)
volume_scale.pack(side = 'right')
新版的hfmix.pyw则可以这样写:
import pygame
from sound_panel import *!导入函数
from tkinter import *
app = Tk()
app.title("Head First Mix")
mixer = pygame.mixer
mixer.init()
//sound_file = "1.WAV"
//track = mixer.Sound(sound_file)
//若添加这两行,可以关闭,但是不正常。即:歌曲依然在播放。
creat_gui(app,mixer,"1.WAV")
creat_gui(app,mixer,"2.WAV")
def shutdown():
track.stop()
app.destroy()
app.protocol("WM_DELETE_WINDOW",shutdown)
app.mainloop()
问题是:虽然可以播放多首歌曲,但是却不能关闭窗口。NameError:全局变量‘track’未定义
4、封装为类class
我们可以创建SoundPanel()类来代替create_gui()
from tkinter import *
import pygame.mixer
class SoundPanel(Frame):
def __init__(self,app,mixer,sound_file):
Frame.__init__(self,app)
self.track = mixer.Sound(sound_file)
self.track_playing = IntVar()
track_button = Checkbutton(self,variable = self.track_playing,command = self.track_toggle,text = sound_file)
track_button.pack(side = 'left')
self.volume = DoubleVar()
self.volume.set(self.track.get_volume())
volume_scale = Scale(self,variable = self.volume,from_ = 0.0,to = 2.0,resolution = 0.1,command = self.change_volume,label = "Volume",orient = HORIZONTAL)
volume_scale.pack(side = 'right')
def track_toggle(self):
if self.track_playing.get() == 1:
self.track.play(loops = -1)
else:
self.track.stop()
def change_volume(self,v):
self.track.set_volume(self.volume.get())
更新的hfmix3.pyw则可以这样写:
import pygame
from sound_panel_class import *
from tkinter import *
app = Tk()
app.title("Head First Mix")
mixer = pygame.mixer
mixer.init()
panel = SoundPanel(app,mixer,"1.WAV")
panel.pack()
panel = SoundPanel(app,mixer,"2.WAV")
panel.pack()
def shutdown():
track.stop()
app.destroy()
app.protocol("WM_DELETE_WINDOW",shutdown)
app.mainloop()
尝试:(1)将def shutdown()写到SoundPanel类中,虽然关了窗口,却关不了播放器。
(2)将track改为pygame.mixer.不过,如果不做修改,直接点击pyw文件可以正常执行。