如果 Tkinter Widget 中的条目已更正,我如何使 tkinter 消息消失?
How do I make a tkinter message disappear if the entry in Tkinter Widget has been corrected?
我创建了一个按钮,如果按下该按钮,它会指向检查功能,这是对用户输入小部件的一种验证检查。
如果用户输入的名字包含字母以外的任何内容,它应该在坐标 (200, 500) 处给出无效检查消息,如果姓氏有这样的错误,则应该在 ( 200, 700) -- 否则屏幕应该进入下一个屏幕。
但是,如果我输入一个错误的条目和一个正确的条目,虽然消息出现在正确的位置 - 当我现在输入错误的条目正确和正确的条目错误时,而不是消息从一个位置消失,它保持原样,另一条消息出现在另一个位置(现在有 2 条消息,甚至认为只有一个条目是错误的)
很抱歉,如果这让您感到困惑,但简而言之,我的目标是该消息应仅出现在输入错误的坐标上,并在输入更正后消失。
我应该如何更改我的代码以确保这一点?
def check(FName_Entry, LName_Entry):
if not FName_Entry.get().isalpha():
errormsg = Message(root, text = 'Invalid entry', anchor = CENTER)
canvas.create_window(200, 500, anchor=NW, window = errormsg)
#messagebox.showerror('Only letters', 'Only letters are allowed!')
if not LName_Entry.get().isalpha():
errormsg2 = Message(root, text='Invalid entry', anchor=CENTER)
canvas.create_window(200, 700, anchor=NW, window=errormsg2)
if FName_Entry.get().isalpha() and LName_Entry.get().isalpha():
canvas.delete("all")
。
.
.
.
Next_button = Button(root, text="Next", anchor=CENTER, command=lambda: check(FName_Entry, LName_Entry))
Next_button.configure(width=10, bg="black", fg="blue", border=10)
canvas.create_window(920, 450, anchor=NW, window=Next_button)
我假设这是您在 selecting 之后到达的部分,无论您是用户还是 driver。如果我们坚持我在你的另一个 post:
中给你的例子
新config.py
from dataclasses import dataclass, asdict
#to make things more complicated and force you to get better
#create a dataclass of default properties
@dataclass
class Button_dc:
bg: str = "white"
fg: str = "gray20"
font: str = 'Calibri 14 bold'
border:int = 10
#make a dict instance of the dataclass
DefaultButton = asdict(Button_dc())
#make a slightly different instance
UserRoleButton = asdict(Button_dc(font='Calibri 24 bold'))
@dataclass
class Label_dc:
bg: str = "steel blue"
fg: str = "gray20"
font: str = 'Calibri 14 bold'
DefaultLabel = asdict(Label_dc())
@dataclass
class Entry_dc:
bg: str = "white"
fg: str = "gray20"
font: str = 'Calibri 14 bold'
width: int = 30
DefaultEntry = asdict(Entry_dc())
@dataclass
class Message_dc:
bg: str = "red"
fg: str = "white"
font: str = 'Calibri 14 bold'
width: int = 150
DefaultMessage = asdict(Message_dc())
在 main.py select 中整个 user_form
方法并将下面的整个粘贴到它的位置
def user_form(self, type, fname=None, lname=None):
self.canvas.delete("all")
self.canvas.create_window(10, 10, anchor='nw', window=tk.Label(self, text="First Name:", **cfg.DefaultLabel))
fname_ent = tk.Entry(self, **cfg.DefaultEntry)
if fname != None:
fname_ent.insert('end', fname)
self.canvas.create_window(120, 10, anchor='nw', window=fname_ent)
self.canvas.create_window(10, 40, anchor='nw', window=tk.Label(self, text="Last Name:", **cfg.DefaultLabel))
lname_ent = tk.Entry(self, **cfg.DefaultEntry)
if lname != None:
lname_ent.insert('end', lname)
self.canvas.create_window(120, 40, anchor='nw', window=lname_ent)
#don't send the entire Entry to the check ~ only the data you want to check
form_next_btn = tk.Button(self, text="next", command=lambda: self.check(type, fname_ent.get(), lname_ent.get()), **cfg.DefaultButton)
self.fnb = self.canvas.create_window(500, 340, anchor='nw', window=form_next_btn)
def check(self, type, fname, lname):
self.canvas.delete(self.fnb)
f = fname.isalpha()
l = lname.isalpha()
if f and l:
self.process(type, fname, lname)
return
if not f:
errormsg = tk.Message(self, text='Invalid entry for first name', **cfg.DefaultMessage)
self.canvas.create_window(10, 90, anchor='nw', window=errormsg)
if not l:
errormsg2 = tk.Message(self, text='Invalid entry for last name', **cfg.DefaultMessage)
self.canvas.create_window(10 if f else 170, 90, anchor='nw', window=errormsg2)
back_btn = tk.Button(self, text="back", command=lambda: self.user_form(type, fname if f else None, lname if l else None), **cfg.DefaultButton)
self.canvas.create_window(500, 340, anchor='nw', window=back_btn)
def process(self, type, fname, lname):
self.canvas.delete("all")
if type is Role.User:
print(f'{fname} {lname} is a user')
elif type is Role.Driver:
print(f'{fname} {lname} is a driver')
旁白: 请记住,我根本没有尝试让您的应用变得漂亮。我只是向您展示如何让它发挥作用。我也没有写出我最好的代码。我会做所有这些完全不同的事情。我正在研究您的 canvas
方法,并为您提供一些理智的东西。在我看来,您使用 canvas 的全部原因只是为了让您可以拥有一个圆角矩形。这似乎不值得,但这不是我的决定。
但是,这些概念并不糟糕,而且在适当的上下文中可以非常强大。让我们以 dataclasses
为例。想象一下,如果您真的想执行以下操作。您最终得到了一个完全自定义的 Text
小部件和一种非常简单的方法来仅更改您需要更改的内容,同时保留您分配的所有其他内容。我为您编写的 dataclasses
是一些小示例概念。您可以进一步扩展这些概念 。
@dataclass
class Text_dc:
background: str = Theme.Topcoat # main element
foreground: str = Theme.Flat
borderwidth: int = 0
selectbackground: str = Theme.Primer # selected text
selectforeground: str = Theme.Accent
selectborderwidth: int = 0 # doesn't seem to do anything ~ supposed to be a border on selected text
insertbackground: str = Theme.Hilight # caret
insertborderwidth: int = 0 # border
insertofftime: int = 300 # blink off millis
insertontime: int = 600 # blink on millis
insertwidth: int = 2 # width
highlightbackground:int = Theme.Topcoat # inner border that is activated when the widget gets focus
highlightcolor: int = Theme.Topcoat # color
highlightthickness: int = 0 # thickness
cursor: str = 'xterm'
exportselection: int = 1
font: str = 'calibri 14'
width: int = 16 # characters ~ often this is ignored as Text gets stretched to fill its parent
height: int = 8 # lines ~ " " " " "
padx: int = 2
pady: int = 0
relief: str = 'flat'
wrap: str = 'word' # "none", 'word'
spacing1: int = 0 # space above every line
spacing2: int = 0 # space between every wrapped line
spacing3: int = 0 # space after return from wrap (paragraph)
state: str = 'normal' # NORMAL=Read/Write | DISABLED=ReadOnly
tabs: str = '4c'
takefocus: int = 1
undo: bool = True
xscrollcommand: Callable = None
yscrollcommand: Callable = None
#common difference
NoWrap = asdict(Text_dc(**{'wrap':'none'}))
NWReadOnly = asdict(Text_dc(**{'wrap':'none','state':'disabled'}))
ReadOnly = asdict(Text_dc(**{'state':'disabled'}))
DefaultText = asdict(Text_dc())
您可以以不同的方式使用该概念。假设您想要一个完全自定义的 Text
小部件,并且您打算做的不仅仅是重新设计它。下面是一个简单粗暴的例子
class ScriptEditor(tk.Text):
def __init__(self, master, **kwargs):
tk.Text.__init__(self, master, **asdict(Text_dc(font='Consolas 14', **kwargs)))
def syntax_highlight(self):
pass
#all the other **kwargs are defaulted internally,
#but we want to adjust the size for this instance
editor = ScriptEditor(root, width=120, height=80)
我创建了一个按钮,如果按下该按钮,它会指向检查功能,这是对用户输入小部件的一种验证检查。
如果用户输入的名字包含字母以外的任何内容,它应该在坐标 (200, 500) 处给出无效检查消息,如果姓氏有这样的错误,则应该在 ( 200, 700) -- 否则屏幕应该进入下一个屏幕。
但是,如果我输入一个错误的条目和一个正确的条目,虽然消息出现在正确的位置 - 当我现在输入错误的条目正确和正确的条目错误时,而不是消息从一个位置消失,它保持原样,另一条消息出现在另一个位置(现在有 2 条消息,甚至认为只有一个条目是错误的)
很抱歉,如果这让您感到困惑,但简而言之,我的目标是该消息应仅出现在输入错误的坐标上,并在输入更正后消失。
我应该如何更改我的代码以确保这一点?
def check(FName_Entry, LName_Entry):
if not FName_Entry.get().isalpha():
errormsg = Message(root, text = 'Invalid entry', anchor = CENTER)
canvas.create_window(200, 500, anchor=NW, window = errormsg)
#messagebox.showerror('Only letters', 'Only letters are allowed!')
if not LName_Entry.get().isalpha():
errormsg2 = Message(root, text='Invalid entry', anchor=CENTER)
canvas.create_window(200, 700, anchor=NW, window=errormsg2)
if FName_Entry.get().isalpha() and LName_Entry.get().isalpha():
canvas.delete("all")
。 . . .
Next_button = Button(root, text="Next", anchor=CENTER, command=lambda: check(FName_Entry, LName_Entry))
Next_button.configure(width=10, bg="black", fg="blue", border=10)
canvas.create_window(920, 450, anchor=NW, window=Next_button)
我假设这是您在 selecting 之后到达的部分,无论您是用户还是 driver。如果我们坚持我在你的另一个 post:
中给你的例子新config.py
from dataclasses import dataclass, asdict
#to make things more complicated and force you to get better
#create a dataclass of default properties
@dataclass
class Button_dc:
bg: str = "white"
fg: str = "gray20"
font: str = 'Calibri 14 bold'
border:int = 10
#make a dict instance of the dataclass
DefaultButton = asdict(Button_dc())
#make a slightly different instance
UserRoleButton = asdict(Button_dc(font='Calibri 24 bold'))
@dataclass
class Label_dc:
bg: str = "steel blue"
fg: str = "gray20"
font: str = 'Calibri 14 bold'
DefaultLabel = asdict(Label_dc())
@dataclass
class Entry_dc:
bg: str = "white"
fg: str = "gray20"
font: str = 'Calibri 14 bold'
width: int = 30
DefaultEntry = asdict(Entry_dc())
@dataclass
class Message_dc:
bg: str = "red"
fg: str = "white"
font: str = 'Calibri 14 bold'
width: int = 150
DefaultMessage = asdict(Message_dc())
在 main.py select 中整个 user_form
方法并将下面的整个粘贴到它的位置
def user_form(self, type, fname=None, lname=None):
self.canvas.delete("all")
self.canvas.create_window(10, 10, anchor='nw', window=tk.Label(self, text="First Name:", **cfg.DefaultLabel))
fname_ent = tk.Entry(self, **cfg.DefaultEntry)
if fname != None:
fname_ent.insert('end', fname)
self.canvas.create_window(120, 10, anchor='nw', window=fname_ent)
self.canvas.create_window(10, 40, anchor='nw', window=tk.Label(self, text="Last Name:", **cfg.DefaultLabel))
lname_ent = tk.Entry(self, **cfg.DefaultEntry)
if lname != None:
lname_ent.insert('end', lname)
self.canvas.create_window(120, 40, anchor='nw', window=lname_ent)
#don't send the entire Entry to the check ~ only the data you want to check
form_next_btn = tk.Button(self, text="next", command=lambda: self.check(type, fname_ent.get(), lname_ent.get()), **cfg.DefaultButton)
self.fnb = self.canvas.create_window(500, 340, anchor='nw', window=form_next_btn)
def check(self, type, fname, lname):
self.canvas.delete(self.fnb)
f = fname.isalpha()
l = lname.isalpha()
if f and l:
self.process(type, fname, lname)
return
if not f:
errormsg = tk.Message(self, text='Invalid entry for first name', **cfg.DefaultMessage)
self.canvas.create_window(10, 90, anchor='nw', window=errormsg)
if not l:
errormsg2 = tk.Message(self, text='Invalid entry for last name', **cfg.DefaultMessage)
self.canvas.create_window(10 if f else 170, 90, anchor='nw', window=errormsg2)
back_btn = tk.Button(self, text="back", command=lambda: self.user_form(type, fname if f else None, lname if l else None), **cfg.DefaultButton)
self.canvas.create_window(500, 340, anchor='nw', window=back_btn)
def process(self, type, fname, lname):
self.canvas.delete("all")
if type is Role.User:
print(f'{fname} {lname} is a user')
elif type is Role.Driver:
print(f'{fname} {lname} is a driver')
旁白: 请记住,我根本没有尝试让您的应用变得漂亮。我只是向您展示如何让它发挥作用。我也没有写出我最好的代码。我会做所有这些完全不同的事情。我正在研究您的 canvas
方法,并为您提供一些理智的东西。在我看来,您使用 canvas 的全部原因只是为了让您可以拥有一个圆角矩形。这似乎不值得,但这不是我的决定。
但是,这些概念并不糟糕,而且在适当的上下文中可以非常强大。让我们以 dataclasses
为例。想象一下,如果您真的想执行以下操作。您最终得到了一个完全自定义的 Text
小部件和一种非常简单的方法来仅更改您需要更改的内容,同时保留您分配的所有其他内容。我为您编写的 dataclasses
是一些小示例概念。您可以进一步扩展这些概念 。
@dataclass
class Text_dc:
background: str = Theme.Topcoat # main element
foreground: str = Theme.Flat
borderwidth: int = 0
selectbackground: str = Theme.Primer # selected text
selectforeground: str = Theme.Accent
selectborderwidth: int = 0 # doesn't seem to do anything ~ supposed to be a border on selected text
insertbackground: str = Theme.Hilight # caret
insertborderwidth: int = 0 # border
insertofftime: int = 300 # blink off millis
insertontime: int = 600 # blink on millis
insertwidth: int = 2 # width
highlightbackground:int = Theme.Topcoat # inner border that is activated when the widget gets focus
highlightcolor: int = Theme.Topcoat # color
highlightthickness: int = 0 # thickness
cursor: str = 'xterm'
exportselection: int = 1
font: str = 'calibri 14'
width: int = 16 # characters ~ often this is ignored as Text gets stretched to fill its parent
height: int = 8 # lines ~ " " " " "
padx: int = 2
pady: int = 0
relief: str = 'flat'
wrap: str = 'word' # "none", 'word'
spacing1: int = 0 # space above every line
spacing2: int = 0 # space between every wrapped line
spacing3: int = 0 # space after return from wrap (paragraph)
state: str = 'normal' # NORMAL=Read/Write | DISABLED=ReadOnly
tabs: str = '4c'
takefocus: int = 1
undo: bool = True
xscrollcommand: Callable = None
yscrollcommand: Callable = None
#common difference
NoWrap = asdict(Text_dc(**{'wrap':'none'}))
NWReadOnly = asdict(Text_dc(**{'wrap':'none','state':'disabled'}))
ReadOnly = asdict(Text_dc(**{'state':'disabled'}))
DefaultText = asdict(Text_dc())
您可以以不同的方式使用该概念。假设您想要一个完全自定义的 Text
小部件,并且您打算做的不仅仅是重新设计它。下面是一个简单粗暴的例子
class ScriptEditor(tk.Text):
def __init__(self, master, **kwargs):
tk.Text.__init__(self, master, **asdict(Text_dc(font='Consolas 14', **kwargs)))
def syntax_highlight(self):
pass
#all the other **kwargs are defaulted internally,
#but we want to adjust the size for this instance
editor = ScriptEditor(root, width=120, height=80)