You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 09:22:05