_tkinter.TclError:Python中的无效命令名

2 投票
1 回答
91 浏览
提问于 2025-04-14 17:05

这是我在这个网站的第一次发言,所以我先简单介绍一下自己。我叫托马斯,来自丹麦,我有一个建筑工程的学士学位,正在业余时间学习Python编程。所以,可以说我在编程方面有点笨,希望大家能帮帮我。

我附上了两个程序的图片,这样更容易理解发生了什么。

我在程序中遇到的问题是,当我把任何一个输入框设置为空字符串时,就会出现一个TclError错误。但这个错误只会在我第二次创建“ForsideMenuFrame”或“LastarrangementMenuFrame”这个框架时发生。所以,我觉得这可能和我销毁这些框架有关。我这样做是为了“清理”一下,以便程序运行得更好,或者至少我觉得是这样。输出中显示的信息是:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Thoma\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:\Users\Thoma\AppData\Local\Programs\Python\Python311\Lib\site-packages\customtkinter\windows\widgets\ctk_entry.py", line 121, in _textvariable_callback
    self._activate_placeholder()
  File "C:\Users\Thoma\AppData\Local\Programs\Python\Python311\Lib\site-packages\customtkinter\windows\widgets\ctk_entry.py", line 299, in _activate_placeholder
    if self._entry.get() == "" and self._placeholder_text is not None and (self._textvariable is None or self._textvariable == ""):
       ^^^^^^^^^^^^^^^^^
  File "C:\Users\Thoma\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 3109, in get
    return self.tk.call(self._w, 'get')
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_tkinter.TclError: invalid command name ".!lastarrangementmenuframe.!ctkentry.!entry"

程序并没有崩溃,它仍然按照我想要的方式运行,只是让我觉得烦,我不知道怎么才能避免这个问题。

下面是我的代码副本,图片应该在下面附上。

import customtkinter as ctk
import settings, forside, lastarrangement, tagudformning

class App(ctk.CTk):
    def __init__(self):
        # Setup
        super().__init__(fg_color = settings.BACKGROUND_COLOR)
        self.title('Snelaster')
        self.geometry('1400x850+50+3')
        self._set_appearance_mode('dark')
        self.iconbitmap('Snow_flake.ico')
        self.resizable(False, False)

        # Layout
        self.rowconfigure(0, weight = 1, uniform = 'a')
        self.rowconfigure(1, weight = 24, uniform = 'a')
        self.columnconfigure(0, weight = 1, uniform = 'a')
        self.columnconfigure(1, weight = 3, uniform = 'a')

        # Dictionary for frames
        self.frames = {
            'forside_menu': None,
            'forside_screen': None,
            'forside_header': None,
            'lastarrangement_menu': None,
            'lastarrangement_screen': None,
            'lastarrangement_header': None,
            'pulttag_menu': None,
            'pulttag_screen': None,
            'pulttag_header': None,
            'sadeltag_menu': None,
            'sadeltag_screen': None,
            'sadeltag_header': None}
        
        # Dictionary for StringVars
        self.string_vars = {
            'entry_sag': ctk.StringVar(),
            'entry_sagsnr': ctk.StringVar(),
            'entry_initialer': ctk.StringVar(),
            'entry_dato': ctk.StringVar()}
        
        # Dictionary for StringVars with tracing
        self.traced_string_vars01 = {
            'entry_C_t': ctk.StringVar(value = '1.0'),
            'combobox_C_top': ctk.StringVar(value = 'Normal'),
            'label_C_top': ctk.StringVar(value = 'C_top\t=\t1.00'),
            'entry_l_1': ctk.StringVar(value = ''),
            'entry_l_2': ctk.StringVar(value = ''),
            'entry_h': ctk.StringVar(value = ''),
            'label_C_s': ctk.StringVar(value = 'C_s\t=\t1.00'),
            'label_C_e': ctk.StringVar(value = 'C_e\t=\t1.00')}
        
        # Start tracing of StringVars
        self.start_trace_string_vars01()

        # Instance of ButtonFrame
        self.button_frame = ButtonFrame(self)
        self.forside_button_click()

        # Run
        self.mainloop()

    # Button commands
    def forside_button_click(self):
        # Change button colors
        self.button_frame.forside_button.configure(fg_color = settings.FORSIDEHEADER_FRAME_COLOR_DARK)
        self.button_frame.lastarrangement_button.configure(fg_color = settings.LASTARRANGEMENTHEADER_FRAME_COLOR)
        self.button_frame.formfaktor_button.configure(fg_color = settings.FORMFAKTORHEADER_FRAME_COLOR)

        # Destroying exsisting frames
        self.destroy_frames()

        # Creating Forside Menu Frame   
        self.frames['forside_menu'] = forside.ForsideMenuFrame(self,
                                                               self.string_vars['entry_sag'],
                                                               self.string_vars['entry_sagsnr'],
                                                               self.string_vars['entry_initialer'],
                                                               self.string_vars['entry_dato'])
        
        # Creating Forside Screen Frame
        self.frames['forside_screen'] = forside.ForsideScreenFrame(self)

        # Creating Forside Header Frame
        self.frames['forside_header'] = forside.ForsideHeaderFrame(self)

    def lastarrangement_button_click(self):
        # Change button colors
        self.button_frame.forside_button.configure(fg_color = settings.FORSIDEHEADER_FRAME_COLOR)
        self.button_frame.lastarrangement_button.configure(fg_color = settings.LASTARRANGEMENTHEADER_FRAME_COLOR_DARK)
        self.button_frame.formfaktor_button.configure(fg_color = settings.FORMFAKTORHEADER_FRAME_COLOR)

        # Destroying exsisting frames
        self.destroy_frames()

        # Creating Lastarrangement Menu Frame
        self.frames['lastarrangement_menu'] = lastarrangement.LastarrangementMenuFrame(self,
                                                                                       self.traced_string_vars01['entry_C_t'],
                                                                                       self.traced_string_vars01['combobox_C_top'],
                                                                                       self.traced_string_vars01['label_C_top'],
                                                                                       self.traced_string_vars01['entry_l_1'],
                                                                                       self.traced_string_vars01['entry_l_2'],
                                                                                       self.traced_string_vars01['entry_h'],
                                                                                       self.traced_string_vars01['label_C_s'],
                                                                                       self.traced_string_vars01['label_C_e'])

        # Creating Lastarrangement Screen Frame
        self.frames['lastarrangement_screen'] = lastarrangement.LastarrangementScreenFrame(self)

        # Creating Lastarrangement Header Frame
        self.frames['lastarrangement_header'] = lastarrangement.LastarrangementHeaderFrame(self)

    def formfaktor_button_click(self):
        # Change button colors
        self.button_frame.forside_button.configure(fg_color = settings.FORSIDEHEADER_FRAME_COLOR)
        self.button_frame.lastarrangement_button.configure(fg_color = settings.LASTARRANGEMENTHEADER_FRAME_COLOR)
        self.button_frame.formfaktor_button.configure(fg_color = settings.FORMFAKTORHEADER_FRAME_COLOR_DARK)

        # Destroying exsisting frames
        self.destroy_frames()

        # Creating Formfaktor Menu Frame
        self.frames['pulttag_menu'] = tagudformning.PulttagMenuFrame(self)

        # Creating Formfaktor Screen Frame
        self.frames['pulttag_screen'] = tagudformning.PulttagScreenFrame(self)

        # Creating Formfaktor Header Frame
        self.frames['pulttag_header'] = tagudformning.PulttagHeaderFrame(self)

    def destroy_frames(self):
        for key, value in self.frames.items():
            if value is not None:
                # Destroying the frame
                self.frames[key].destroy()
                self.frames[key] = None

    def start_trace_string_vars01(self):
        for value in self.traced_string_vars01.values():
            value.trace('w', self.trace_string_vars01)

    def trace_string_vars01(self, *args):
        # entry_C_t
        C_t = self.traced_string_vars01['entry_C_t'].get()
        if len(C_t) == 2 and C_t[0] == '0' and C_t[1] != '.' or len(C_t) > 0 and C_t[0] == '.':
            self.traced_string_vars01['entry_C_t'].set('0')
        try:
            C_t = float(C_t)
            if C_t > 1:
                self.traced_string_vars01['entry_C_t'].set('1.0')
        except ValueError:
            if C_t == '':
                pass
            else:
                self.traced_string_vars01['entry_C_t'].set('')

        # label_C_top
        topografi = self.traced_string_vars01['combobox_C_top'].get()
        C_top = 1.00
        if topografi == 'Afskærmet':
            C_top = 1.25
        elif topografi == 'Normal':
            C_top = 1.00
        elif topografi == 'Vindblæst':
            C_top = 0.80
        self.traced_string_vars01['label_C_top'].set(f'C_top\t=\t{C_top:.2f}')

        # entry l_1
        l_1 = self.traced_string_vars01['entry_l_1'].get()
        if len(l_1) == 2 and l_1[0] == '0' and l_1[1] != '.' or len(l_1) > 0 and l_1[0] == '.':
            self.traced_string_vars01['entry_l_1'].set('')
        try:
            l_1 = float(l_1)
        except ValueError:
            if l_1 == '':
                pass
            else:
                self.traced_string_vars01['entry_l_1'].set('')

        # entry l_2
        l_2 = self.traced_string_vars01['entry_l_2'].get()
        if len(l_2) == 2 and l_2[0] == '0' and l_2[1] != '.' or len(l_2) > 0 and l_2[0] == '.':
            self.traced_string_vars01['entry_l_2'].set('')
        try:
            l_2 = float(l_2)
        except ValueError:
            if l_2 == '':
                pass
            else:
                self.traced_string_vars01['entry_l_2'].set('')

        # entry h
        h = self.traced_string_vars01['entry_h'].get()
        if len(h) == 2 and h[0] == '0' and h[1] != '.' or len(h) > 0 and h[0] == '.':
            self.traced_string_vars01['entry_h'].set('')
        try:
            h = float(h)
        except ValueError:
            if h == '':
                pass
            else:
                self.traced_string_vars01['entry_h'].set('')

        # label C_s
        try:
            C_s = 1.00
            if topografi == 'Afskærmet':
                C_s = 1.00
            elif 2 * h > l_1:
                C_s = 1.00
            else:
                if l_2 <= 10 * h:
                    C_s = 1.00
                elif l_2 >= 20 * h:
                    C_s = 1.25
                else:
                    C_s = 1 + 0.025 * ((l_2 - 10 * h) / h)
            self.traced_string_vars01['label_C_s'].set(f'C_s\t=\t{C_s:.2f}')
        except TypeError:
            pass

        # label C_e
        C_e = C_top * C_s
        self.traced_string_vars01['label_C_e'].set(f'C_e\t=\t{C_e:.2f}')
    
class ButtonFrame(ctk.CTkFrame):
    def __init__(self, parent):
        # Setup
        super().__init__(master = parent, 
                         fg_color = settings.BUTTON_FRAME_COLOR)
        self.grid(row = 0, column = 0, sticky = 'nsew')

        # Create instance of parent (App)
        self.parent = parent

        # Layout
        self.rowconfigure(0, weight = 1, uniform = 'a')
        self.columnconfigure((0,1,2), weight = 1, uniform = 'a')

        # Button font
        font = ctk.CTkFont(family = settings.FONT_FAMILY,
                           size = settings.BUTTON_FONT_SIZE,
                           weight = 'bold')

        # Button widgets
        self.forside_button = ctk.CTkButton(self, 
                                       text = 'Forside', 
                                       font = font,
                                       text_color = 'white',
                                       fg_color = settings.FORSIDEHEADER_FRAME_COLOR,
                                       hover_color = settings.FORSIDEHEADER_FRAME_COLOR_DARK,
                                       corner_radius = settings.BUTTON_CORNER_RADIUS,
                                       command = self.parent.forside_button_click)
        self.forside_button.grid(row = 0, column = 0, 
                                 sticky = 'nsew')

        self.lastarrangement_button = ctk.CTkButton(self, 
                                               text = 'Lastarrangement', 
                                               font = font,
                                               text_color = 'white',
                                               fg_color = settings.LASTARRANGEMENTHEADER_FRAME_COLOR,
                                               hover_color = settings.LASTARRANGEMENTHEADER_FRAME_COLOR_DARK,
                                               corner_radius = settings.BUTTON_CORNER_RADIUS,
                                               command = self.parent.lastarrangement_button_click)
        self.lastarrangement_button.grid(row = 0, column = 1, 
                                         sticky = 'nsew')

        self.formfaktor_button = ctk.CTkButton(self, 
                                          text = 'Formfaktor', 
                                          font = font,
                                          text_color = 'white',
                                          fg_color = settings.FORMFAKTORHEADER_FRAME_COLOR,
                                          hover_color = settings.FORMFAKTORHEADER_FRAME_COLOR_DARK,
                                          corner_radius = settings.BUTTON_CORNER_RADIUS,
                                          command = self.parent.formfaktor_button_click)
        self.formfaktor_button.grid(row = 0, column = 2, 
                                    sticky = 'nsew')

if __name__ == '__main__':
    App()

Forside Lastarrangement

这是我尝试过的,但没有成功。在程序开始时,我导入了_tkinter。

import customtkinter as ctk
import settings, forside, lastarrangement, tagudformning
import _tkinter as _tk

然后在App类的trace_string_vars01方法中,我尝试捕获TclError错误,然后忽略它。

 # entry_C_t
        try:
            C_t = self.traced_string_vars01['entry_C_t'].get()
            if len(C_t) == 2 and C_t[0] == '0' and C_t[1] != '.' or len(C_t) > 0 and C_t[0] == '.':
                self.traced_string_vars01['entry_C_t'].set('0')
            try:
                C_t = float(C_t)
                if C_t > 1:
                    self.traced_string_vars01['entry_C_t'].set('1.0')
            except ValueError:
                if C_t == '':
                    pass
                else:
                    self.traced_string_vars01['entry_C_t'].set('')
        except _tk.TclError:
            pass

1 个回答

1

这个错误提示是说问题出在 costumtkinter 这个包里,源代码给了你几个可能出错的地方。

你可以通过把一个变量设置为空字符串,或者使用配置占位符失去焦点删除方法,或者通过创建一个新的输入框来解决这个问题。

另外,你的错误是指向这个输入框:
".!lastarrangementmenuframe.!ctkentry.!entry"
虽然你提供了很多代码,但在这种情况下还不够,因为 lastarrangement.LastarrangementMenuFrame 是在一个导入的模块里定义的。

这个错误:

_tkinter.TclError: invalid command name ".!lastarrangementmenuframe.!ctkentry.!entry"

意味着你或者 StringVar,或者某个事件指向了一个已经不存在的控件。

撰写回答