【问题标题】:Tkinter Error, _tkinter.TclError: can't delete Tcl commandTkinter 错误,_tkinter.TclError:无法删除 Tcl 命令
【发布时间】:2021-09-14 23:10:06
【问题描述】:

我开始在美容院管理系统上工作,到目前为止一切似乎都运行良好,但在管理面板中,我创建了一个动画导航侧边栏,每次关闭页面时,我都会收到“无法删除 TCL命令”。对此有何想法?此外,任何关于代码的提示和意见都将受到高度赞赏。

完全错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1885, in __call__
    return self.func(*args)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 2306, in destroy
    Misc.destroy(self)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 632, in destroy
    self.tk.deletecommand(name)
_tkinter.TclError: can't delete Tcl command

代码:

from tkinter import *

import setuptools.command.alias
from PIL import Image, ImageTk

class AdminPage:
    def __init__(self):

        # Creating main window
        self.adminPageWindow = Tk()
        self.adminPageWindow.bind("<Escape>", self.minimizeScreen)
        self.adminPageWindow.bind("<F11>", self.maximizeScreen)
        self.adminPageWindow.attributes("-fullscreen", True)
        self.adminPageWindow.config( bg="#FFFFFF")

        # Creating Nav Bar
        # Creating default Vars
        self.min_w = 50  # Minimum width of the frame
        self.max_w = 135  # Maximum width of the frame
        self.cur_width = self.min_w  # Increasing width of the frame
        self.expanded = False  # Check if it is completely expanded

        # Creating the Images from existing files
        self.logoImage = ImageTk.PhotoImage (Image.open ('Resources/Images/Logo.png').resize ((30, 30), Image.ANTIALIAS))
        self.dashboard_img = ImageTk.PhotoImage (Image.open ('Resources/Images/Dashboard_img.png').resize ((40, 40), Image.ANTIALIAS))
        self.new_img = ImageTk.PhotoImage (Image.open ('Resources/Images/New_img.png').resize ((40, 40), Image.ANTIALIAS))
        self.stock_img = ImageTk.PhotoImage (Image.open ('Resources/Images/stock_img.png').resize ((40, 40), Image.ANTIALIAS))
        self.pay_img = ImageTk.PhotoImage (Image.open ('Resources/Images/pay_img.png').resize ((40, 40), Image.ANTIALIAS))
        self.profile_img = ImageTk.PhotoImage (Image.open ('Resources/Images/profile_img.png').resize ((40, 40), Image.ANTIALIAS))

        self.adminPageWindow.update ()

        self.navbar = Frame (self.adminPageWindow, width=50, height=self.adminPageWindow.winfo_height (), bg="#FEF17D")
        self.navbar.pack(side=LEFT)

        # Creating Corresponding
        self.dashboard_button = Button(self.navbar,image=self.dashboard_img,bg='#FEF17D',relief='flat', command=self.dashboardPage)
        self.new_button = Button(self.navbar, image=self.new_img, bg="#FEF17D", relief='flat')
        self.stock_button = Button(self.navbar, image=self.stock_img, bg="#FEF17D", relief='flat')
        self.pay_button = Button(self.navbar, image=self.pay_img, bg="#FEF17D", relief='flat')
        self.profile_button = Button(self.navbar, image=self.profile_img, bg="#FEF17D", relief='flat')

        self.emptyLabel = Label(self.navbar, image=self.logoImage, bg="#FEF17D").grid(row=0, column=0, pady=5, padx=5)
        self.dashboard_button.grid(row=1, column=0, pady=40)
        self.new_button.grid(row=2, column=0, pady=40)
        self.stock_button.grid(row=3, column=0, pady=40)
        self.pay_button.grid(row=4, column=0, pady=40)
        self.profile_button.grid(row=5, column=0, pady=40)

        self.navbar.bind('<Enter>', lambda e: self.expand())
        self.navbar.bind('<Leave>', lambda e: self.contract())
        self.navbar.grid_propagate(False)

        self.headerFrame = Frame(self.adminPageWindow, bg="#FEF17D", height=50)
        self.headerFrame.pack(fill=X)

        self.mainFrame = Frame (self.adminPageWindow, bg="#FFFFFF", width=self.adminPageWindow.winfo_width () - 50 ,height=self.adminPageWindow.winfo_height () - 150)
        self.mainFrame.pack()
        self.footerFrame = Frame(self.adminPageWindow, bg="#FFFFFF", width=self.adminPageWindow.winfo_width()-50, height=50)
        self.footerFrame.pack(fill=X, side=BOTTOM)

        self.headerFrameLabel = Label(self.headerFrame, text="Admin Panel", font=("Courier New Italic Bold", 18), bg="#FEF17D")
        self.headerFrameLabel.pack(anchor=CENTER, pady=5)
        text = "Salon Management System V1.00\nCreated by Nael Ghannam"
        self.footerFrameLabel = Label(self.footerFrame, text=text, font=("Courier New Italic", 10), bg="#FFFFFF")
        self.footerFrameLabel.pack()




        self.adminPageWindow.mainloop()

    def minimizeScreen(self, event):
        self.adminPageWindow.attributes ('-fullscreen', False)
        window_Width = 1280
        window_height = 720

        screenWidth = self.adminPageWindow.winfo_screenwidth ()
        screen_Height = self.adminPageWindow.winfo_screenheight ()

        position_top = int (screen_Height / 2 - window_height / 2)
        position_right = int (screenWidth / 2 - window_Width / 2)

        self.adminPageWindow.geometry (f"{window_Width}x{window_height}+{position_right}+{position_top}")
        return None
    def maximizeScreen(self, event):
        self.adminPageWindow.attributes ('-fullscreen', True)
        return None
    def expand(self):
        self.cur_width += 10  # Increase the width by 10
        rep = self.adminPageWindow.after (5, self.expand)  # Repeat this func every 5 ms
        self.navbar.config (width=self.cur_width)  # Change the width to new increase width
        if self.cur_width >= self.max_w:  # If width is greater than maximum width
            self.expanded = True  # Frame is expended
            self.adminPageWindow.after_cancel (rep)  # Stop repeating the func
            self.fill()
    def contract(self):
        self.cur_width -= 10  # Reduce the width by 10
        rep = self.adminPageWindow.after (5, self.contract)  # Call this func every 5 ms
        self.navbar.config (width=self.cur_width)  # Change the width to new reduced width
        if self.cur_width <= self.min_w:  # If it is back to normal width
            self.expanded = False  # Frame is not expanded
            self.navbar.after_cancel (rep)  # Stop repeating the func
            self.fill()
    def fill(self):
        if self.expanded:  # If the frame is exanded
            # Show a text, and remove the image
            self.dashboard_button.config (text='Dashboard', image='', font=("Courier New Italic", 14))
            self.new_button.config (text='New Entries', image='', font=("Courier New Italic", 14))
            self.stock_button.config (text='Stock', image='', font=("Courier New Italic", 14))
            self.pay_button.config (text='Pay', image='', font=("Courier New Italic", 14))
            self.profile_button.config (text='Profiles', image='', font=("Courier New Italic", 14))
        else:
            # Bring the image back
            self.dashboard_button.config (image=self.dashboard_img, font=(0, 21))
            self.new_button.config (image=self.new_img, font=(0, 21))
            self.stock_button.config (image=self.stock_img, font=(0, 21))
            self.pay_button.config (image=self.pay_img, font=(0, 21))
            self.profile_button.config (image=self.profile_img, font=(0, 21))

    def dashboardPage(self):
        self.headerFrameLabel.config(text="Dashboard")


AdminPage()

【问题讨论】:

  • Have a look here.。我已经在按钮上实现了这一点,但你可以为 Frames 做到这一点
  • 您能否发布完整的错误回溯? CoolCloud 也实现了类似的here
  • 首先应该将self.adminPageWindow.update () 更改为self.adminPageWindow.update_idletasks()。这将使tkinter 有时间处理所有这些图像。
  • @Derek .update() 也会给tkinter 时间来处理所有这些图像。 .update() 做了.update_idletasks() 所做的一切,甚至更多。它还可以处理事件,所以如果你不小心它可能会导致RecursionErrors。
  • @TheLizzard 它们相似但不完全相同。 update_idletasks 将进入事件循环,直到所有空闲回调都被调用。这将更新窗口的显示,但不会更新用户引起的事件。这可能会影响几何管理器,因此 TkToplevel 可能无法在那里完成初始化。

标签: tkinter


【解决方案1】:

尝试将您的 expand 和您的 contract 函数更改为:

def expand(self):
    self.cur_width += 10  # Increase the width by 10
    self.navbar.config(width=self.cur_width)  # Change the width to new increase width
    if self.cur_width >= self.max_w:  # If width is greater than maximum width
        self.expanded = True  # Frame is expended
        self.fill()
    else:
        rep = self.adminPageWindow.after(5, self.expand)  # Repeat this func every 5 ms

def contract(self):
    self.cur_width -= 10  # Reduce the width by 10
    self.navbar.config(width=self.cur_width)  # Change the width to new reduced width
    if self.cur_width <= self.min_w:  # If it is back to normal width
        self.expanded = False  # Frame is not expanded
        self.fill()
    else:
        rep = self.adminPageWindow.after(5, self.contract)  # Call this func every 5 ms

您会注意到我移动了代码,因此您无需致电after_cancel。我认为问题在于after_cancel 取消了.after 脚本,但tkinter 并未将其从内存中删除,因此当您关闭窗口时它再次尝试将其删除。据我所知,这可能是tkinter 中的一个错误。

【讨论】:

    猜你喜欢
    • 2022-11-18
    • 1970-01-01
    • 1970-01-01
    • 2017-10-04
    • 1970-01-01
    • 2021-05-15
    • 2013-07-07
    • 2016-05-04
    相关资源
    最近更新 更多