我喜欢将生产代码与 GUI 代码隔离。我想通过消息队列设置/检索小部件值。
因此,给定一个命名小部件,我认为我可以将名称与设置/检索消息一起传递,并让 gui 代码将名称与小部件实例关联起来。
不幸的是,我不能简单地传递小部件名称,我需要传递小部件路径,如下所示:
leftwindow.button_grid.my_button1
。
我不希望生产代码需要知道完整路径,因为它与我的隔离目的相矛盾,并且如果重新排列 gui 中的小部件,它可能会发生变化。
我知道,我可以从顶级窗口开始运行递归循环,并将每个小部件的名称与感兴趣的小部件的名称进行比较。例如:是否可以在 Tkinter 中按名称搜索小部件?
但是,每次我需要设置/获取小部件值时执行此操作会降低性能。
有人知道如何以更有效的方式执行此操作,仅给出小部件名称而不指定完整的小部件路径吗?
我的想法是实现一个自己的解析器,它将小部件伪路径转换为实际的小部件路径,例如:
def translate_widget_pseudo_path(wpath: str):
wpath = wpath.replace("process_control_buttons", "leftwindow.button_grid")
wpath = wpath.replace("...", "...")
return wpath
这样,我可以隔离我的代码,为生产代码提供稳定的伪路径,并让 gui 决定伪路径的哪一部分转换为 gui 元素的实际路径的哪一部分。
我制作了一个程序,其中有一个搜索条目小部件。当您搜索您喜欢的小部件并输入(或者如果按下“前往”按钮)时,光标将转到所需的条目小部件。发挥创意并进行修改以搜索部分文本。根据您的要求更改。
from tkinter import *
from tkinter import messagebox as mb
def goto_wdgt():
x = dct['search_lbl'].get()
# the actual key in the dct is search term + '_lbl'
x = x + '_lbl'
x = x.lower()
if x == '':
mb.showinfo('Enter Widget Name', 'Enter the widget Name or go to the widget directly')
elif x in dct.keys():
dct[x].focus_set()
else:
mb.showinfo('Wrong widget', f'There is no widget with name {x} available')
root = Tk()
root.geometry('500x700')
# Create a dct -all keys in small letters, for entry widgets value being blank
dct = { 'search': '',
'search_lbl' : 'xxxx',
'name': '',
'name_lbl':'xxxx',
'phone number': '',
'phone number_lbl' : 'xxxx',
'address 1st line' : '',
'address 1st line_lbl' : 'xxxx',
'address 2nd line': '',
'address 2nd line_lbl' : 'xxxx',
'pincode' : '',
'pincode_lbl' : 'xxxx'
}
#iterate thru dct to pack each widget
for key, val in dct.items():
#if value is empty, the widget should be a Label and the text should be key.capitalize()
if val == '':
dct[key] = Label(root, text = key.capitalize())
dct[key].pack(side='top')
# if value is not empty the widget should be entry widget
else:
dct[key] = Entry(root)
dct[key].pack(side='top')
# if key is 'search_lbl', we need a btn after that to initiate search, map btn with function goto_wdgt
if key == 'search_lbl':
btn = Button(root, text = 'Go', command = goto_wdgt)
btn.pack(side='top')
# Bind return-key with btn so that search can also be initiated by pressing 'enter'
dct['search_lbl'].bind('<Return>', lambda evnt: btn.invoke())
root.mainloop()