我试图编写一个待办事项列表。当我点击按钮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