tkinter:以有效的方式按名称搜索小部件

问题描述 投票:0回答:1

我喜欢将生产代码与 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 元素的实际路径的哪一部分。

python-3.x user-interface tkinter message-queue isolation
1个回答
0
投票

我制作了一个程序,其中有一个搜索条目小部件。当您搜索您喜欢的小部件并输入(或者如果按下“前往”按钮)时,光标将转到所需的条目小部件。发挥创意并进行修改以搜索部分文本。根据您的要求更改。

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()
© www.soinside.com 2019 - 2024. All rights reserved.