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

Tkinter闪卡应用无法切换加载文件的技术问题

CustomTkinter闪卡应用文件切换崩溃问题修复

问题现象

基于CustomTkinter开发的闪卡测验应用,启动时能正常读取Python脚本所在目录下Text文件夹内的txt文件,但切换文件时(无论是切换到新文件还是原文件)都会触发FileNotFoundError,无法找到目标文件。

错误根源

问题出在getFiles()函数中的os.chdir("../Code/Text")语句:

  • 应用启动时,当前工作目录是脚本所在的Code文件夹,此时Text/文件名的相对路径有效
  • 调用os.chdir后,当前工作目录被切换到Text文件夹,后续FileHandling函数仍用Text/文件名的路径,实际会去Text/Text/文件名找文件,自然不存在

修复方案

避免修改当前工作目录,改用绝对路径定位Text文件夹,确保无论何时都能正确找到文件:

  1. 获取当前脚本所在的绝对目录
  2. 拼接出Text文件夹的绝对路径
  3. 用绝对路径读取文件和遍历txt文件

修复后的完整代码

from customtkinter import *
from CTkMessagebox import CTkMessagebox
import glob
import os

information = []
file_name = 'keywords.txt'
app = None
# 获取当前脚本所在目录的绝对路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# 拼接Text文件夹的绝对路径
TEXT_DIR = os.path.join(BASE_DIR, "Text")

def hide(tk):
    # 隐藏窗口
    try:
        tk.withdraw()
    except:
        pass

def show(tk):
    # 显示窗口
    tk.deiconify()

def FileHandling(filename):
    # 文件读取处理
    information = []
    # 使用绝对路径打开文件
    file_path = os.path.join(TEXT_DIR, filename)
    with open(file_path, 'r', encoding='utf-8') as f:
        temp = f.read().split("\n")

    for i in range(0, len(temp), 2):
        if i+1 >= len(temp):
            break  # 避免最后一行只有单个内容导致索引越界
        temp_list = []
        temp_list.append(temp[i].capitalize())
        temp_list.append(temp[i+1].capitalize())
        information.append(temp_list)
    return information

def changeHandler(value):
    global file_name
    file_name = value
    print(value)
    return file_name

def changeFile():
    # 切换文件逻辑
    files = getFiles()
    filePicker(files)

def getFiles():
    temp = []
    # 遍历Text文件夹下的txt文件,无需切换目录
    for file in glob.glob(os.path.join(TEXT_DIR, "*.txt")):
        # 只保留文件名,不保留路径
        temp.append(os.path.basename(file))
    return temp

def filePicker(files):
    hide(app)
    FilePicker = CTkToplevel()
    FilePicker.geometry("500x400")
    FilePicker.resizable(False, False)
    FilePicker.title("文件选择器")
    Title = CTkLabel(
        master=FilePicker, text="选择要加载的文件", font=("Arial", 10))
    Title.place(relx=0.5, rely=0.05, anchor="center")

    Options = CTkComboBox(FilePicker, values=files,
                          variable="未选择", command=changeHandler)  # type: ignore
    Options.place(relx=0.5, rely=0.5, anchor="center")

    ExitBtn = CTkButton(master=FilePicker, text="返回菜单",
                        fg_color="#550000", text_color="#000000", command=lambda: Menu(FilePicker)).place(relx=0.5, rely=0.7, anchor="center")

def Menu(tk=None):
    global information
    information = FileHandling(file_name)
    global app
    # 创建主窗口或显示已存在的窗口
    if app == None:
        app = CTk()
        app.geometry("500x400+750+300")
        app.resizable(False, False)
        app.title("闪卡应用")
        set_appearance_mode("dark")

        Title = CTkLabel(master=app, text="闪卡项目",
                         font=("Arial", 40))
        PlayBtn = CTkButton(master=app, text="开始测验",
                            fg_color="#005500", text_color="#000000", command=lambda: Run(app))
        Changebtn = CTkButton(master=app, text="切换文件",
                              fg_color="#AA4203", text_color="#000000", command=changeFile)
        ExitBtn = CTkButton(master=app, text="退出",
                            fg_color="#550000", text_color="#000000", command=app.quit)

        Title.place(relx=0.5, rely=0.05, anchor="center")
        PlayBtn.place(relx=0.5, rely=0.4, anchor="center")
        Changebtn.place(relx=0.5, rely=0.5, anchor="center")
        ExitBtn.place(relx=0.5, rely=0.6, anchor="center")
        app.mainloop()
        exit()
    else:
        show(app)
        try:
            tk.destroy()
        except:
            pass

# 补充Run函数(原代码中未定义,避免报错)
def Run(tk):
    hide(tk)
    # 这里可以添加闪卡测验的逻辑
    TestWindow = CTkToplevel()
    TestWindow.geometry("500x400")
    TestWindow.title("闪卡测验")
    # 示例标签
    Label(TestWindow, text="闪卡测验界面").pack(pady=20)
    # 返回菜单按钮
    CTkButton(TestWindow, text="返回菜单", command=lambda: [hide(TestWindow), Menu()]).pack(pady=10)

Menu()

额外优化点

  • 增加了文件读取时的编码指定(encoding='utf-8'),避免中文乱码
  • 处理了txt文件最后一行可能只有单个内容的情况,防止索引越界
  • 补充了原代码中缺失的Run函数,避免点击"开始"按钮时报错
  • 把界面文本改成了中文,更符合使用习惯

内容的提问来源于stack exchange,提问作者C0d3_404

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:13:24