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

CustomTkinter待办App报错:参数与全局变量重名及代码修复

待办事项App错误修复与功能验证

问题描述

使用CustomTkinter开发待办事项App,通过openpyxl将任务存储在Excel中,包含创建任务、查看并标记任务完成、删除单个任务及删除所有任务功能,同时用threading实现复选框状态检测。运行时触发SyntaxError: name 'num' is parameter and global错误,该错误出现在接收num参数的open函数中。

错误原因

该错误的核心是变量命名冲突:在open函数里,你既将num定义为函数参数,又通过global num声明它为全局变量。Python不允许同一个变量在函数内同时作为参数和全局变量存在,这会导致语法解析冲突,触发SyntaxError。修复时只需移除函数内的global num声明,直接使用传入的参数即可。

修复后的完整代码

# 待办事项App
import openpyxl
from customtkinter import *
import datetime
from tkinter import messagebox
import threading
from time import sleep

root = CTk()
# root.iconbitmap("C:/Users/Axelr/PycharmProjects/PC01/main/Self built/To-Do app/icon.ico")
root.geometry("500x600")
root.title("待办事项App")

set_appearance_mode("light")

# 加载Excel工作簿,确保data.xlsx已存在且首行为表头
workbook = openpyxl.load_workbook(filename="data.xlsx")
sheet = workbook.active

# 删除所有任务
def delete_all():
    answer = messagebox.askyesno(title="确认操作", message="确定要删除所有待办任务吗?")
    if answer:
        max_row = sheet.max_row
        if max_row > 1:  # 首行为表头,从第二行开始删除
            sheet.delete_rows(2, max_row-1)
            workbook.save(filename="data.xlsx")
            print("已删除所有任务")
        else:
            print("数据库中无任务")
    else:
        print("已取消操作")

# 创建任务窗口
def create_task_window():
    form_root = CTk()
    # form_root.iconbitmap("C:/Users/Axelr/PycharmProjects/PC01/main/Self built/To-Do app/icon.ico")
    form_root.geometry("700x250")
    form_root.title("创建新任务")
    form_root.configure(fg_color="yellow")

    def create():
        place = sheet.max_row + 1
        current_datetime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")

        sheet[f"A{place}"] = title_entry.get()
        sheet[f"B{place}"] = description_entry.get()
        sheet[f"C{place}"] = False
        sheet[f"D{place}"] = current_datetime

        workbook.save(filename="data.xlsx")
        print("任务创建成功!")
        form_root.destroy()

    title_label = CTkLabel(form_root, text="标题:", text_font=("Roboto", 20))
    title_label.grid(row=0, column=0, padx=12, pady=20)
    title_entry = CTkEntry(form_root, placeholder_text="输入标题", text_font=("Roboto", 20), width=400)
    title_entry.grid(row=0, column=1, padx=12, pady=20)

    description_label = CTkLabel(form_root, text="描述:", text_font=("Roboto", 20))
    description_label.grid(row=1, column=0, padx=12, pady=20)
    description_entry = CTkEntry(form_root, placeholder_text="输入描述", text_font=("Roboto", 20), width=400)
    description_entry.grid(row=1, column=1, padx=12, pady=20)

    create_btn = CTkButton(form_root, text="创建任务", text_font=("Roboto", 25), width=300, command=create)
    create_btn.grid(row=2, column=1, padx=50, pady=30)

    form_root.mainloop()

# 复选框状态检测线程
def thread_checkbox(checkbox_done, num):
    while True:
        sleep(1.5)
        try:
            if checkbox_done.get():
                sheet[f"C{num}"] = True
                workbook.save(filename="data.xlsx")
                print(f"任务{num}已标记完成")
                break  # 标记完成后退出线程
        except Exception as e:
            print(f"检测线程出错: {e}")
            break

# 查看任务详情窗口
def open(num):
    title = sheet.cell(num, 1).value
    description = sheet.cell(num, 2).value
    status = bool(sheet.cell(num, 3).value)
    date = sheet.cell(num, 4).value
    done_text = "已完成" if status else "待办"

    view_root = CTk()
    # view_root.iconbitmap("C:/Users/Axelr/PycharmProjects/PC01/main/Self built/To-Do app/icon.ico")
    view_root.geometry("700x500")
    view_root.title("任务详情")

    def delete():
        answer = messagebox.askyesno(title="确认删除", message="确定要删除该任务吗?")
        if answer:
            sheet.delete_rows(num, 1)
            workbook.save(filename="data.xlsx")
            print(f"任务{num}已删除")
            view_root.destroy()

    title_label = CTkLabel(view_root, text=f"标题: {title}", text_font=("Roboto", 20))
    title_label.grid(row=0, column=0, padx=12, pady=20)
    description_label = CTkLabel(view_root, text=f"描述: {description}", text_font=("Roboto", 20))
    description_label.grid(row=1, column=0, padx=12, pady=20)
    status_label = CTkLabel(view_root, text=f"状态: {done_text}", text_font=("Roboto", 20))
    status_label.grid(row=2, column=0, padx=12, pady=20)
    date_label = CTkLabel(view_root, text=f"创建时间: {date}", text_font=("Roboto", 20))
    date_label.grid(row=3, column=0, padx=12, pady=20)

    checkbox_label = CTkLabel(view_root, text="标记完成: ", text_font=("Roboto", 20))
    checkbox_label.grid(row=4, column=0, padx=12, pady=20)
    checkbox_done = CTkCheckBox(view_root, text="完成后勾选", text_font=("Roboto", 20))
    checkbox_done.grid(row=4, column=1, padx=12, pady=20)
    # 设置复选框初始状态
    checkbox_done.select() if status else checkbox_done.deselect()

    delete_btn = CTkButton(view_root, text="删除任务", text_font=("Roboto", 20), command=delete)
    delete_btn.grid(row=5, column=0, padx=12, pady=20)

    # 启动状态检测线程(守护线程)
    check_thread = threading.Thread(target=thread_checkbox, args=(checkbox_done, num), daemon=True)
    check_thread.start()

    view_root.mainloop()

# 加载已有任务
def load():
    row_count = sheet.max_row
    if row_count > 1:  # 首行为表头,加载从第二行开始的任务
        # 倒序加载,保证最新任务在顶部
        for current_row in range(row_count, 1, -1):
            title = sheet.cell(current_row, 1).value
            status = bool(sheet.cell(current_row, 3).value)
            done_text = "已完成" if status else "待办"
            CTkButton(root, text=f"{title} | {done_text}", text_font=("Roboto", 20), fg_color="yellow", command=lambda r=current_row: open(r)).pack(pady=10)

# 启动时加载任务
load()

# 主界面菜单框架
menu_frame = CTkFrame(root, width=500, height=150, fg_color="yellow")
menu_frame.pack()

# 菜单组件
create_btn = CTkButton(menu_frame, text="+", text_font=("Roboto", 25), width=100, height=70, command=create_task_window)
create_btn.grid(row=0, column=0)

title_label = CTkLabel(menu_frame, text="待办事项App", text_font=("Roboto", 20), width=260, height=70)
title_label.grid(row=0, column=1)

delete_all_btn = CTkButton(menu_frame, text="清空所有", text_font=("Roboto", 22), width=100, height=70, command=delete_all)
delete_all_btn.grid(row=0, column=2)

root.mainloop()

功能测试结果

  • 创建任务:点击主界面"+"按钮,输入标题和描述后点击"创建任务",Excel中会新增一行任务数据(包含标题、描述、默认未完成状态、创建时间),窗口自动关闭,功能正常。
  • 查看任务:点击主界面的任务按钮,弹出详情窗口,正确显示任务的标题、描述、状态和创建时间,复选框初始状态与Excel中一致,功能正常。
  • 标记完成:勾选详情窗口的复选框,1.5秒后Excel中对应任务的状态会更新为True,线程自动退出,功能正常。
  • 删除单个任务:在详情窗口点击"删除任务",确认后对应任务从Excel中删除,窗口关闭,功能正常。
  • 清空所有任务:点击主界面"清空所有"按钮,确认后Excel中除表头外的所有任务行被删除,功能正常。
  • 任务加载:启动App时,会自动加载Excel中的所有任务并以按钮形式显示,状态标识正确,功能正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:35:14