如何为Tkinter/CustomTkinter应用中的ShimejiBlock添加滚动条
解决Shimeji Tool的垂直滚动问题
问题核心
当前代码直接将ShimejiBlock组件放置在主窗口上,没有使用支持滚动的容器,导致Shimeji文件夹数量过多时内容超出屏幕范围。需要借助CustomTkinter的CTkScrollableFrame作为容器,实现垂直滚动功能。
修改后的完整代码
import threading import os import shutil import tkinter import customtkinter from tkinter import filedialog from PIL import Image, ImageTk customtkinter.set_appearance_mode("dark") customtkinter.set_default_color_theme("dark-blue") class ShimejiBlock: def __init__(self, parent_frame, folder_name: str): self.folder_path = f'./Shimeji/{folder_name}/' # 安全获取jar文件,避免索引报错 jar_files = [f for f in os.listdir(self.folder_path) if f.endswith('.jar')] self.jar_file = jar_files[0] if jar_files else None if not self.jar_file: print(f"警告:{folder_name}文件夹中未找到jar文件") return # 安全获取ico文件 ico_files = [f for f in os.listdir(self.folder_path) if f.endswith('.ico')] self.ico_file = ico_files[0] if ico_files else None if not self.ico_file: print(f"警告:{folder_name}文件夹中未找到ico文件") return self.folder_name = folder_name # 单个Shimeji的容器框架 self.block_frame = customtkinter.CTkFrame(parent_frame, fg_color="#141414", width=400, height=100) self.block_frame.pack(pady=8, padx=20, fill="x") # 加载并显示图标 try: img = Image.open(os.path.join(self.folder_path, self.ico_file)).resize((100,100)) self.image = ImageTk.PhotoImage(img) icon_label = customtkinter.CTkLabel(self.block_frame, image=self.image, text="") icon_label.place(x=10, y=0) except Exception as e: print(f"加载图标失败:{e}") icon_label = customtkinter.CTkLabel(self.block_frame, text="无图标", width=100, height=100) icon_label.place(x=10, y=0) # 启动按钮 button = customtkinter.CTkButton( self.block_frame, width=250, height=100, text=folder_name, command=self.openShimeji, bg_color="#141414", fg_color="#141414", hover_color="#2a2a2a", anchor="e", border_spacing=25 ) button.place(x=120, y=0) def openShimeji(self): if self.jar_file: OpenShimeji(self.folder_name, self.jar_file) def UpdateShimeji(scroll_frame, folder_name): ShimejiBlock(scroll_frame, folder_name) def open_jar_file(folder_name, jar_file): try: os.chdir(f'./Shimeji/{folder_name}') os.system(jar_file) except Exception as e: print(f"启动Shimeji失败:{e}") def FileExplorer(scroll_frame): folder_path = filedialog.askdirectory() if not folder_path: return folder_name = os.path.basename(folder_path) target_path = f'./Shimeji/{folder_name}' if not os.path.exists(target_path): try: shutil.copytree(folder_path, target_path) UpdateShimeji(scroll_frame, folder_name) except Exception as e: print(f"复制文件夹失败:{e}") def OpenShimeji(name, jar): jar_thread = threading.Thread(target=open_jar_file, args=(name, jar), daemon=True) jar_thread.start() def DetectShimeji(scroll_frame): shimeji_dir = './Shimeji' if not os.path.exists(shimeji_dir): os.makedirs(shimeji_dir) return ShimejiFolderList = os.listdir(shimeji_dir) for folder_name in ShimejiFolderList: folder_path = os.path.join(shimeji_dir, folder_name) if os.path.isdir(folder_path): jar_files = [f for f in os.listdir(folder_path) if f.endswith('.jar')] if jar_files: ShimejiList.append(ShimejiBlock(scroll_frame, folder_name)) if __name__ == "__main__": ShimejiList = [] app = customtkinter.CTk() app.geometry("500x440") app.minsize(width=500, height=440) app.maxsize(width=500, height=440) app.title("Shimeji Tool") # 加载窗口图标(确保ico.png存在) try: ico = Image.open('ico.png') photo = ImageTk.PhotoImage(ico) app.wm_iconphoto(False, photo) except Exception as e: print(f"加载窗口图标失败:{e}") # 顶部工具栏 bar = customtkinter.CTkFrame(app, fg_color='#404040', height=22, corner_radius=0) bar.grid(row=0, column=0, sticky="ew") app.grid_columnconfigure(0, weight=1) fileButton = customtkinter.CTkButton( bar, command=lambda: FileExplorer(scroll_frame), fg_color='#292929', hover_color='#242424', text="添加Shimeji", corner_radius=0, width=80 ) fileButton.pack(side="left") # 滚动框架:放置所有ShimejiBlock scroll_frame = customtkinter.CTkScrollableFrame(app, fg_color='gray8') scroll_frame.grid(row=1, column=0, sticky="nsew") app.grid_rowconfigure(1, weight=1) DetectShimeji(scroll_frame) app.mainloop()
关键改动说明
- 使用
CTkScrollableFrame作为ShimejiBlock的父容器,自动实现垂直滚动 - 将每个
ShimejiBlock封装到独立的CTkFrame中,用pack布局替代place,确保滚动时组件位置正确 - 增加文件存在性检查和异常捕获,避免因缺失jar/ico文件导致程序崩溃
- 修复
UpdateShimeji函数的参数错误,确保新添加的Shimeji能正确放入滚动框架 - 调整工具栏和滚动框架的布局,使用
grid并设置sticky和weight,适配固定窗口大小 - 将启动线程设为守护线程,关闭窗口时自动终止后台进程
内容的提问来源于stack exchange,提问作者Camouflage_kid
相关产品推荐
相关产品推荐

