_tkinter.TclError:无效的命令名称“。!label4”

时间:2019-12-21 11:32:26

标签: python tkinter

当我运行此命令并输入testuser凭据时,它们都可以正常运行,并在登录状态窗口小部件上显示带有绿色文本的窗口。

working colour

但是,当我然后删除凭据并输入随机密码以便收到错误消息时,它不是红色并生成此错误堆栈(如果我尝试重新输入正确的凭据,也会发生同样的事情)

nonworking colour

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Program Files\Python38\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File (my path to file), line 194, in get_info
    login_status_widget.config(fg="red")
  File "C:\Program Files\Python38\lib\tkinter\__init__.py", line 1637, in configure
    return self._configure('configure', cnf, kw)
  File "C:\Program Files\Python38\lib\tkinter\__init__.py", line 1627, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: invalid command name ".!label4"

我不知道为什么会收到此错误,特别是因为仅当我更改凭据时才会发生此错误-旁注,使用错误的登录名会产生相同的结果,即使用红色文本,之后的任何内容均不会产生颜色。 / p>

这是我的完整代码,考虑到我不知道错误从何而来,因此我无法提供相关部分,尽管这可能是我在类或某种东西中实现此错误的方式。

# Stuff to implement: other widgets in root class, actual GUI for program (ideas: restaurant manager, GUI creator)


# Import tkinter as the alias tk, import mainloop from tkinter
import tkinter as tk
from tkinter import mainloop

# Key Aliases for widget.bind("<Key>",function): "<Return>" = Enter key  aka return key

class Root(): # Define Root class for GUI windows
    """
    Root is the main window class for the GUI which returns an instance with a Tk window, which can then be used to run class functions to return a widget on the window.

    Parameters:
    grid_allowed (True/False) e.g. variable = Root(True) which would mean grid_allowed would be set to True 

    Functions:
    add_button(text, command={function name}, grid_coord=[{row number},{column number}], name="{any string}"): 

    add_label(text, grid_coord=[{row},{column}], name="{any string}"): 

    add_entry(bind={alias of key e.g. "<Return>"}, function={function to be called when key is pressed}, show={character}, grid_coord=[{row number},{column number}], name="{any string}"): 

    return_lists(): Returns a list containing label_list, button_list and entry_list

    delete_widget(name): If a widget with the matching name is found, destroy it

    return_widget(name): If a widget with the matching name is found, return it, else return None

    check_widget(name): If a widget with the matching name is found, return True, else return False

    Notes:
    remember to run {Root instance}.window.mainloop() at the end of the program 

    """

    def __init__(self,grid_allowed,title): # Initialise the class
        self.title = title
        self.window = tk.Tk()   
        self.window.title(self.title)
        self.button_list = []
        self.label_list = []  
        self.entry_list = []
        self.grid_allowed = grid_allowed


    def add_button(self,text,command=None,grid_coord=None,name=None): # Function to add a button onto the window of the Root class instance
        self.command = command 
        self.text = text
        self.grid_coord = grid_coord
        self.name = name

        try: # Tries to create a button with a command and if an error is caught, creates a button without a command
            self.button = tk.Button(self.window,text=self.text,command=self.command)
        except Exception:
            self.button = tk.Button(self.window,text=self.text)

        if self.grid_allowed: # Checks if the class attribute self.grid_allowed is True, if so uses grid manager, else uses pack manager
            self.button.grid(row=self.grid_coord[0],column=self.grid_coord[1])
        else:
            self.button.pack()

        if self.name == None: # Checks if the button has not been given a name and if it has adds a name into the list with the button object
            self.button_list.append(self.button)
        else:
            self.button_list.append([self.name,self.button])


    def add_label(self,text,grid_coord=None,name=None): # Function to add a label onto the window of the Root class instance
        self.text = text 
        self.grid_coord = grid_coord
        self.label = tk.Label(self.window,text=self.text)#
        self.name = name

        if self.grid_allowed: # Checks if the class attribute self.grid_allowed is True, if so uses grid manager, else uses pack manager
            self.label.grid(row=self.grid_coord[0],column=self.grid_coord[1])
        else:
            self.label.pack()

        if self.name == None: # Checks if the label has not been given a name and if it has adds a name into the list with the label object
            self.label_list.append(self.label)
        else:
            self.label_list.append([self.name,self.label])


    def add_entry(self,bind=None,function=None,grid_coord=None,show=None,name=None): # Function to add a entry onto the window of the Root class instance
        self.bind = bind
        self.function = function
        self.grid_coord = grid_coord
        self.show = show
        self.name = name

        if not self.show == None: # Checks if the parameter show has been passed, and if it has then force the entry to only show those characters
            self.entry = tk.Entry(self.window,show=self.show)
        else:
            self.entry = tk.Entry(self.window)

        if not self.bind == None: # Checks if the parameter bind has been passed, and if it has then bind the specified key to the specified function
            self.entry.bind(self.bind,self.function)

        if self.grid_allowed: # Checks if the class attribute self.grid_allowed is True, if so uses grid manager, else uses pack manager
            self.entry.grid(row=self.grid_coord[0],column=self.grid_coord[1])
        else:
            self.entry.pack()

        if self.name == None: # Checks if the entry has not been given a name and if it has adds a name into the list with the entry object
            self.entry_list.append(self.entry)
        else:
            self.entry_list.append([self.name,self.entry])


    def return_lists(self): # Function to return a list of the lists containing the widgets created on the Root class instance
        return [self.label_list, self.button_list, self.entry_list]


    def delete_widget(self,name): # Function to iterate over all the widgets created on the Root class instance and delete the one with the same name that is passed as a parameter if found
        self.name = name

        for widget_list in [self.button_list,self.entry_list,self.label_list]: # Iterates over list, of lists of types of widgets
            for widget in widget_list: # Iterates over indiviual widget type list
                try:
                    if widget[0] == self.name: # If the widget has a name and it is the same as the passed parameter, destroy the widget
                        widget[1].destroy()
                except Exception: # If the widget is not found on the current iteration then ignore that widget
                    pass


    def return_widget(self,name): # Function to iterate over all the widgets created on the Root class instance and if one is found with the same name that is passed as a parameter return it
        self.name = name

        for widget_list in [self.button_list,self.entry_list,self.label_list]: # Iterates over list, of lists of types of widgets
            for widget in widget_list: # Iterates over indiviual widget type list
                try:
                    if widget[0] == self.name: # If the widget has a name and it is the same as the passed parameter, return the widget object
                        return widget[1] 
                except Exception:
                    return_bln = None # If the correct widget is not found return None
        return return_bln

    def check_widget(self,name): # Function to iterate over all the widgets created on the Root class instance and if one is found with the same name that is passed as a parameter return True
        self.name = name

        for widget_list in [self.button_list,self.entry_list,self.label_list]: # Iterates over list, of lists of types of widgets
            for widget in widget_list:  # Iterates over indiviual widget type list
                try:
                    if widget[0] == self.name: # If the widget has a name and it is the same as the passed parameter, returns True
                    return True
                except Exception:
                    return_bln = False # If the correct widget is not found return None

        return return_bln





# Actual GUI creation below

def main():
    main_window = Root(True,"Login") # Create an instance of Root class and assign main_window to it
    main_window.window.resizable(0,0) # Prevent user from resizing the window
    main_window.window.geometry("300x90") # Setting the original size of the window to '300x90'

    user_dict = {
        "testuser":"test",
}

    def check_login(username,password): # Function to take a username and password as parameters and return True if they are a valid user, else return False
        try:
            if user_dict[username] == password: # If the username exists check if the password is correct and return True if it is, False if it isn't
                return True
            else:
                return False
        except Exception: 
            return False # If the user doesn't exist return False

    def get_info(): # Function to handle login event on button click
        password = main_window.return_widget("password").get() # Get the current value of the password widget from main_window
        username = main_window.return_widget("username").get() # Get the current value of the username widget from main_window
        email = main_window.return_widget("email").get() # Get the current value of the email widget from main_window

        login_status = check_login(username,password) # Calls function with the username and password obtained from the widgets and assigns login_status to result

        if main_window.check_widget("login status"): # If the error message/success message already exist, delete the widget
            main_window.delete_widget("login status")

        if login_status: # If the username and password were correct, add a label widget to the window saying 'Login successful', else add a label widget to the window saying 'Your username or password is incorrect'
            main_window.add_label("Login successful",grid_coord=[3,1],name="login status")
            login_status_widget = main_window.return_widget("login status")
            login_status_widget.config(fg="green")
        else:
            main_window.add_label("Your username or password is incorrect",grid_coord=[3,1],name="login status")
            login_status_widget = main_window.return_widget("login status")
            login_status_widget.config(fg="red")


    main_window.add_label("Username",grid_coord=[0,0])  # Create the basic layout of the window
    main_window.add_entry(grid_coord=[0,1],name="username") 
    main_window.add_label("Password",grid_coord=[1,0]) 
    main_window.add_entry(show="*",grid_coord=[1,1],name="password")
    main_window.add_label("Email",grid_coord=[2,0])
    main_window.add_entry(grid_coord=[2,1],name="email")
    main_window.add_button(text="Login",command=get_info,grid_coord=[3,0])

    list_array = main_window.return_lists() # Get the lists of all the widgets from main_window

    main_window.window.mainloop() # Start the mainloop of the GUI to show the window 

if __name__ == "__main__": # If the python script is being run in cmd, call main function
    main()

1 个答案:

答案 0 :(得分:0)

在删除窗口小部件时,我没有使用我专门创建的delete_widget函数,而是返回了窗口小部件,然后将其称为widget.destroy()。

我现在已解决此问题,并且工作正常。

感谢Bryan Oakley帮助我实现了错误的根源。