Python Tkinter共享变量进行唯一检查



我试图编写一个待办事项列表。当我点击按钮self.button_check将颜色从白色条目更改为绿色时,它一直有效,直到我创建第二个条目。问题是带有新检查的新条目。按钮还查找用于第一个的变量self.check_var。我现在的问题是:有没有办法检查条目的当前bg颜色,改变条目是白色还是绿色,而不是使用self.check_var变量?

由于明显的错误,我刚开始编码😅

import tkinter as tk
from tkinter.constants import ANCHOR, CENTER, X
class App():
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("To-Do-List")
        self.window.geometry("700x700")
        self.x_but, self.y_but = 0.05, 0.2 
        self.x_ent, self.y_ent = 0.05, 0.2
        self.x_but2 = 0.3
        self.check_var = True
        self.start_frame()
        self.grid1()
        self.window.mainloop()
        
    def start_frame(self):
        self.label1 = tk.Label(text="To Do List", font=("", 30))
        self.label1.place(relx=0.5, rely=0.05, anchor=CENTER)
    def grid1(self):
        self.button1 = tk.Button(text="Create", command= self.create_field)
        self.button1.place(relx = self.x_but, rely= self.y_but)
    def create_field(self):
        self.y_but += 0.05
        self.button1.place(relx= self.x_but, rely= self.y_but)
        self.entry1 = tk.Entry()
        self.entry1.place(relx= self.x_ent, rely= self.y_ent)
        x = self.entry1
        
        self.button_check = tk.Button(text="✅", height= 1,command=lambda x=self.entry1: self.check(x))
        self.button_check.place(relx= self.x_but2, rely=self.y_ent)
       

        self.y_ent += 0.05
    
    def check(self,ent):
        if self.check_var:
            ent.configure(bg="Green")
            self.check_var = False
        else:
            ent.configure(bg="White")
            self.check_var = True
    
app = App()

您可以将值分配给Entry本身:

def create_field(self):
    self.y_but += 0.05
    self.button1.place(relx= self.x_but, rely= self.y_but)
    
    # you don't need to use `self.` here necessarily, the instance attribute will get
    # overwritten anyways when you create a new `Entry`, same for button below
    entry = tk.Entry()
    entry.place(relx= self.x_ent, rely= self.y_ent)
    # create an attribute for the `Entry` and set it to True
    # when you pass the `Entry` to the function, you will be able to 
    # access this attribute too
    entry.check_var = True
    button_check = tk.Button(text="✅", height= 1,command=lambda x=entry: self.check(x))
    button_check.place(relx= self.x_but2, rely=self.y_ent)
    self.y_ent += 0.05

然后更改check方法:

# add this decorator because the method doesn't require `self` anymore
@staticmethod
def check(ent):
    # here you can access the `Entry`'s attribute `check_var`
    # which was created in the other method
    if ent.check_var:
        ent.configure(bg="Green")
        ent.check_var = False
    else:
        ent.configure(bg="White")
        ent.check_var = True

此外,我建议您使用pack而不是place,因为在这种情况下使用它要容易得多(现在可能更难适应(。您不需要使用tkinter中的常量,它们只包含一个同名的字符串,因此您可以很容易地使用该字符串,例如:anchor='center'

我认为您在这里可以做的是,您可以将条目对象和check_var存储为字典中的键和值,而不是使用全局check_var。这样,由于它是一个待办事项应用程序,您可以通过使用entry对象对字典进行索引来轻松获取值。

class App():
    def __init__(self):
        ....
        self.info = {} # Create a dictionary
    
    def create_field(self):
        .....
        self.entry1 = tk.Entry()
        self.entry1.place(relx= self.x_ent, rely= self.y_ent)
        
        self.button_check = tk.Button(text="✅", height= 1,command=lambda x=self.entry1: self.check(x))
        self.button_check.place(relx= self.x_but2, rely=self.y_ent)
       
        self.info[self.entry1] = False # Add the item to the dictionary
    
    def check(self,ent):
        check_var = self.info[ent]
        
        if not check_var: ent.configure(bg="Green")
        else: ent.configure(bg="White")
        self.info[ent] = not check_var

同样,如果你想在未来扩展应用程序,你可以在字典中添加更多与给定任务相关的信息,比如任务文本本身。也许类似于:

def create_field(self):
    self.y_but += 0.05
    self.button1.place(relx= self.x_but, rely= self.y_but)
    self.entry1 = tk.Entry()
    self.entry1.place(relx= self.x_ent, rely= self.y_ent)
    
    tk.Button(text="✅", height= 1,command=lambda x=self.entry1: self.check(x)).place(relx= self.x_but2, rely=self.y_ent)
    tk.Button(text="Get details", height= 1,command=lambda x=self.entry1: self.get_details(x)).place(relx= self.x_but2+0.05, rely=self.y_ent)
    tk.Button(text="Update details", height= 1,command=lambda x=self.entry1: self.update_details(x)).place(relx= self.x_but2+0.17, rely=self.y_ent)
    
    data = '', False
    self.info[self.entry1] = data
    self.y_ent += 0.05
def check(self,ent):
    idx       = self.info[ent]
    check_var = idx[1]
    if not check_var:
        ent.configure(bg="Green")
        self.info[ent] = ent.get(),True
    else:
        ent.configure(bg="White")
        self.info[ent] = ent.get(),False
        
def get_details(self,ent):
    idx       = self.info[ent] # Get the details
    text      = idx[0]
    check_var = idx[1]
    print(f'The task is: {text} and it is {"completed" if check_var else "incomplete"}') # Print the details
def update_details(self,ent):
    idx       = self.info[ent] # Get the item
    check_var = idx[1] # Get the flag
    data      = ent.get(), check_var # Make a tuple of data
    
    self.info[ent] = data # Update the info

最新更新