如何实现可拖动扩展的Tkinter音乐播放器GUI窗口
解决Tkinter音乐播放器窗口拖动扩展时曲目文本截断问题
问题根源
- 给
Listbox设置了固定width=25,窗口扩展时无法自动加宽 - 控制按钮的
control_frame未指定正确的grid位置,导致布局错位 - 存在变量拼写错误(
curent_song应为current_song)
修复方案
移除Listbox固定宽度
删除Listbox初始化时的width=25参数,配合sticky='NSEW'让组件随所在列宽度自动拉伸。修正控制栏布局
将control_frame定位到窗口底部并跨所有列,避免按钮区域错位:control_frame.grid(row=2, column=0, columnspan=5, pady=10)同时调整按钮在
control_frame内部的行号为0,保证排列整齐。添加水平滚动条(可选)
针对超长曲目名,添加水平滚动条,即使窗口宽度不足也能查看完整文本。修复变量拼写与逻辑优化
修正curent_song拼写错误,优化曲目切换逻辑用取模运算实现循环切换,避免索引越界。
修改后的完整代码
import tkinter as tk from tkinter import ttk from tkinter import * from tkinter import filedialog import pygame import os import customtkinter as ctk from PIL import Image, ImageTk root = tk.Tk() root.title('Music Player') pygame.mixer.init() menubar = Menu(root) root.config(menu=menubar) songs = [] current_song = "" # 修复拼写错误 paused = False def load_music(): global current_song root.directory = filedialog.askdirectory() # 清空原有列表,避免重复加载 songlist.delete(0, END) songs.clear() for song in os.listdir(root.directory): name, ext = os.path.splitext(song) if ext == '.mp3': songs.append(song) for song in songs: songlist.insert("end", song) if songs: songlist.selection_set(0) current_song = songs[songlist.curselection()[0]] def play_music(): global current_song, paused if not paused: pygame.mixer.music.load(os.path.join(root.directory, current_song)) pygame.mixer.music.play() else: pygame.mixer.music.unpause() paused = False def pause_music(): global paused pygame.mixer.music.pause() paused = True def next_music(): global current_song, paused try: current_idx = songs.index(current_song) next_idx = (current_idx + 1) % len(songs) songlist.selection_clear(0, END) songlist.selection_set(next_idx) current_song = songs[next_idx] play_music() except: pass def previous_music(): global current_song, paused try: current_idx = songs.index(current_song) prev_idx = (current_idx - 1) % len(songs) songlist.selection_clear(0, END) songlist.selection_set(prev_idx) current_song = songs[prev_idx] play_music() except: pass organise_menu = Menu(menubar , tearoff=False) organise_menu.add_command(label='select Folder' , command=load_music) menubar.add_cascade(label='organise' , menu=organise_menu) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ STYLING s = ttk.Style() s.configure('mainFrame.TFrame', background = '#7FFF00') #GREEN s.configure('Frame2.TFrame', background = '#FF1493') #PINK! s.configure('Frame3.TFrame', background = '#FF1493') #PINK! s.configure('Frame4.TFrame', background = '#7FFF00')#GREEN s.configure('Frame5.TFrame', background = '#7FFF00')#GREEN s.configure('Frame6.TFrame', background = '#FF1493')#PINK! s.configure('Frame7.TFrame', background = '#FF1493')#PINK! s.configure('Frame8.TFrame', background = '#7FFF00')#GREEN s.configure('Horizontal.TFrame', background = '#CDC5BF') s.configure('Verticle.TFrame', background = '#FFD93C') # 修正颜色值错误 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ WIDGETS mainFrame = ttk.Frame(root, width = 250, height = 250, style='mainFrame.TFrame') mainFrame.grid(row = 0, column = 1, sticky = 'NSEW') Frame2 = ttk.Frame(root, width = 250, height = 250, style = 'Frame2.TFrame') Frame2.grid(row = 1, column = 1, sticky = 'NSEW') Frame3 = ttk.Frame(root, width = 250, height = 250, style = 'Frame3.TFrame') Frame3.grid(row = 0, column = 2, sticky = 'NSEW') Frame4 = ttk.Frame(root, width = 250, height = 250, style = 'Frame4.TFrame') Frame4.grid(row = 1, column = 2, sticky = 'NSEW') Frame5 = ttk.Frame(root, width = 250, height = 250, style = 'Frame5.TFrame') Frame5.grid(row = 0, column = 3, sticky = 'NSEW') Frame6 = ttk.Frame(root, width = 250, height = 250, style = 'Frame6.TFrame') Frame6.grid(row = 1, column = 3, sticky = 'NSEW') Frame7 = ttk.Frame(root, width = 250, height = 250, style = 'Frame7.TFrame') Frame7.grid(row = 0, column = 4, sticky = 'NSEW') Frame8 = ttk.Frame(root, width = 250, height = 250, style = 'Frame8.TFrame') Frame8.grid(row = 1, column = 4, sticky = 'NSEW') # 添加水平滚动条 scrollbar = Scrollbar(root, orient=HORIZONTAL, command=songlist.xview) scrollbar.grid(row=2, column=0, sticky='EW') # 移除固定width,绑定滚动条 songlist = Listbox(root, bg="black", fg="white", borderwidth=0, highlightthickness=0, height=15, xscrollcommand=scrollbar.set) songlist.grid(row = 0, rowspan = 2, column = 0, sticky = 'NSEW') #~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GRID CONFIGURATION root.columnconfigure(0, weight = 1) root.columnconfigure(1, weight = 2) root.columnconfigure(2, weight = 2) root.columnconfigure(3, weight = 2) root.columnconfigure(4, weight = 2) root.rowconfigure(0, weight = 1) root.rowconfigure(1, weight = 1) root.rowconfigure(2, weight = 0) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ BUTTONS play_btn_image = PhotoImage(file='play.png') pause_btn_image = PhotoImage(file='pause.png') next_btn_image = PhotoImage(file='next.png') back_btn_image = PhotoImage(file='back.png') control_frame = Frame(root) # 控制栏定位到底部跨列 control_frame.grid(row=2, column=0, columnspan=5, pady=10) play_btn = Button(control_frame, image=play_btn_image, borderwidth=0, command=play_music) pause_btn = Button(control_frame, image=pause_btn_image, borderwidth=0, command=pause_music) next_btn = Button(control_frame, image=next_btn_image, borderwidth=0, command=next_music) back_btn = Button(control_frame, image=back_btn_image, borderwidth=0, command=previous_music) # 按钮在控制栏内第一行排列 play_btn.grid(row=0, column=1, padx=7, pady=10) pause_btn.grid(row=0, column=2, padx=7, pady=10) next_btn.grid(row=0, column=3, padx=7, pady=10) back_btn.grid(row=0, column=0, padx=7, pady=10) root.mainloop()
关键修改说明
- Listbox自适应宽度:删除固定宽度后,窗口向右拖动时Listbox会随列宽自动拉伸,完整显示曲目名。
- 控制栏布局修正:将控制栏放在窗口底部并跨所有列,避免按钮区域与左侧列表错位。
- 水平滚动条:针对超长曲目名,提供滚动查看的备选方案。
- 逻辑优化:曲目切换用取模运算实现循环播放,避免索引越界报错。
内容的提问来源于stack exchange,提问作者NMW81
相关产品推荐
相关产品推荐

