问题描述
在阅读之前: 我是一个完整的编程新手,更不用说Python了。我不期待解决方案。即使我只是得到一个正确方向的指针,我也会很感激。如果您觉得我请求帮助的方式不成熟,请告诉我,以便下次我需要帮助时,我会做得更好。
目标: 我正在制作一个程序来测试如何根据需要关注的小部件让程序做出响应。目前,我只是让它通过显示“什么”有焦点来响应。 最终,一旦我弄清楚了这一点,我就可以将我学到的知识应用到我正在处理的另一个程序中,即专注于输入字段将导致所有输入的字段清除。所以很自然地,我希望这个程序不仅可以更改标签,还可以更改条目小部件。稍后再说。
进展: 我设法让程序打印出哪个小部件在终端和标签小部件中都有焦点。
问题: 我的问题是消息很难看,我希望它看起来更整洁。
问题示例: 不是说“Entry has focus”,而是说“.!frame.!entry {has focus}”
我试过: 检查其他人是否制作了类似的程序。我发现的唯一一个是我如何取得如此大的进步,但它并没有使文本更好。我还在各种网站上研究了 Python 如何处理我在这个程序中使用的某些命令。 我是编程新手,所以我承认我不完全确定运行该程序的最佳方式是什么,因此尝试研究它对我来说很困难。
代码:
# Call tkinter tools
from tkinter import *
from tkinter import ttk
"""
Todo:
Add different widgets that can 'gain' focus.
Print in the terminal which widget has focus.
Change entry and label text depending on which widget has focus.
"""
# Develop the window and frame
root = Tk()
root.title("Focus Test")
root.columnconfigure(0,weight = 1)
root.rowconfigure(0,weight = 1)
frame = ttk.Frame(root,padding = "1 1 1 1")
frame.grid(column = 0,row = 0,sticky = (N,S,E,W))
# Resizes columns in frame
for col in range(1,3):
frame.columnconfigure(col,weight = 1)
# Resizes rows in frame
for row in range(1,3):
frame.rowconfigure(row,weight = 1)
# Add response label
foc_labvar = StringVar()
foc_labvar.set("No focus")
foc_lab = ttk.Label(frame,width = 7,textvariable = foc_labvar)
foc_lab.grid(column = 2,row = 2,sticky = (W,E))
# Add entry Box
foc_entvar = StringVar()
foc_entvar.set("Entry widget")
foc_ent = ttk.Entry(frame,textvariable = foc_entvar)
foc_ent.grid(column = 1,row = 1,E))
# Add button
foc_butvar = StringVar()
foc_butvar.set("Button widget")
foc_but = ttk.Button(frame,textvariable = foc_butvar)
foc_but.grid(column = 2,E))
# Focus commands
def focus(event):
focused_widget = frame.focus_get()
foc_labvar.set((focused_widget,"has focus"))
print(focused_widget,"has focus")
# Bind mouse click to run focus command
root.bind("<Button-1>",focus)
# Resize widgets inside frame
for child in frame.winfo_children():
child.grid_configure(padx = 5,pady = 5)
root.mainloop()
解决方法
您可以通过 event
处理小部件标识部分轻松完成此操作,例如:
def focus(event):
focused_widget = event.widget.winfo_class()
foc_labvar.set((focused_widget,"has focus")) # Or f'{focused_widget} has focus'
print(focused_widget,"has focus")
此处 event
将为小部件提供 widget
方法,然后您可以在其上使用任何小部件方法,例如 focus()
或 insert()
(如果它是入口小部件)等等。此处 winfo_class
应该可以使用,因为它是一种通用方法并且适用于所有小部件。
有关 winfo_class
的更多信息,它将提供小部件的类,例如 TButton
表示按钮,因为 tk
就是这样引用它们的。如果您仍然坚持要摆脱 T
,那么只需使用 event.widget.winfo_class()[1:]
将 'T' 去掉。
您可以使用 Tkinter winfo_class()
函数来获取小部件对象类型(请注意,每个类型前面都有一个“T”字符,因此我检查了 TEntry/TButton 而不仅仅是 Entry/Button)。
def focus(event):
focused_widget = frame.focus_get().winfo_class()
if focused_widget == 'TEntry':
foc_labvar.set("Entry has focus")
print('Entry has focus')
elif focused_widget == 'TButton':
foc_labvar.set("Button has focus")
print('Button has focus')
,
您可以像这样使用 if
语句:
def focus(event):
focused_widget = frame.focus_get() # You can also use `event.widget` like what @CoolCloud did.
if focused_widget == foc_ent:
foc_labvar.set("Entry has focus")
if focused_widget == foc_but:
foc_labvar.set("Button has focus")
,
您可以为小部件指定一个您选择的名称。然后您可以使用 winfo_name
来获取小部件的名称。关于名称的唯一要求是它不能包含句点。
此外,您应该绑定到 <FocusIn>
和 <FocusOut>
,这样即使焦点通过键盘发生变化,您的代码也能正常工作。
foc_ent = ttk.Entry(...,name="foc entry")
foc_but = ttk.Button(...,name="foc button")
...
def focus(event):
focused_widget = frame.focus_get()
if focused_widget:
foc_labvar.set(f"{focused_widget.winfo_name()} as focus")
else:
foc_labvar.set("nothing has focus")
root.bind("<FocusIn>",focus)
root.bind("<FocusOut>",focus)
,
结合提供的建议。这是我最终得到的结果,它按照我在脑海中想象的方式工作,并从每个人的帮助中获得了一些额外的帮助:
# Focus commands
def focus(event):
focused_widget = event.widget.winfo_class()[1:]
foc_labvar.set(focused_widget + " has focus")
foc_entvar.set(focused_widget + " has focus")
print(focused_widget,"has focus")
# Bind mouse and keyboard to run focus command
root.bind("<Button-1>",focus)
root.bind("<FocusIn>",focus)