有一個框架,其中包含許多標簽和文本小部件。這些是從 JSON 檔案動態生成的。
我想要的是將焦點設定在 Frame 中的第一個 Text 小部件上。該 Text 小部件的名稱取決于 JSON 檔案,因此我不能僅使用Frame.children['name'].
這是一個可以完成作業的函式。但我想知道是否有更方便的方法可以做到這一點。我想過在鍵盤遍歷層次結構中獲取第一個小部件,但找不到任何示例。請提出任何建議。謝謝。
def focus_to_child(event):
for k, v in event.widget.children.items():
if type(v) is Text:
break
try:
event.widget.children[k].focus()
except UnboundLocalError:
pass
最小的可重現示例。下面的示例中的小部件比我的專案中的要少得多。因此,第一個 Text 小部件是鍵盤遍歷層次結構中 Treeview 之后的下一個小部件。不要讓這個事實讓你感到困惑 =)
from random import randint as ri
from tkinter import Tk, ttk, Text
# here's example struct and values, in project MAP is initialized from JSON documents
MAP = {'_a_A': {'_id': '_a_A', 'name': chr(ri(97, 122)), 'quit_prob': 0.1, 'changed': False},
'_a_B': {'_id': '_a_B', 'name': chr(ri(97, 122)), 'quit_prob': 0.25, 'changed': False},
'_x_Z': {'_id': '_x_Z', 'name': chr(ri(97, 122)), 'quit_prob': 0.75, 'changed': True}}
# Treeview items selection event handle
def tv_sel_handler(event):
try:
# item id of the document that user has selected
sel_iid = event.widget.selection()[0]
except IndexError:
sel_iid = ''
try:
generate_entries(MAP[sel_iid])
# here we should set focus to the first Text in the data_entries Frame
focus_to_child()
except KeyError:
pass
# this is my option at the moment, but I doubt that it's the most convenient method
def focus_to_child():
for k, v in data_entries.children.items():
if type(v) is Text:
break
try:
data_entries.children[k].focus()
except UnboundLocalError:
pass
# generate Entries for selected document fields
def generate_entries(document):
def focus_widget(event):
if event.state == 8:
event.widget.tk_focusNext().focus()
elif event.state == 9:
event.widget.tk_focusPrev().focus()
return 'break'
row = 0
for field in document.keys():
# label
ttk.Label(data_entries, text=field).grid(row=row, column=0, sticky='nw')
# widget to edit document fields
tf = Text(data_entries, name=field, wrap='word', width=20, height=2)
tf.insert('1.0', document[field])
tf.grid(row=row 1, sticky='nwe', padx=0, pady=5)
tf.bind('<Tab>', focus_widget)
tf.bind('<Shift-Tab>', focus_widget)
tf.bind('<FocusIn>', lambda event: event.widget.tag_add('sel', '1.0', 'end'))
# separator
ttk.Label(data_entries).grid(row=row 2)
row = 3
root = Tk()
# list of documents
data_docs = ttk.Treeview(root, selectmode='browse', show=('tree',))
data_docs.column('#0', width=220)
data_docs.grid(row=0, column=0, sticky='nsw')
data_docs.bind('<<TreeviewSelect>>', tv_sel_handler)
for doc in MAP.values():
data_docs.insert('', 'end', doc['_id'], text=doc['_id'][3:])
# frame for dynamic entries
data_entries = ttk.Frame(root, width=1000, height=450, padding=(15,0))
data_entries.grid(row=0, column=1, sticky='nsew')
root.mainloop()
uj5u.com熱心網友回復:
我不知道方便,但更直接和有效的方法是簡單地記住創建它們時第一個文本小部件是什么——這很容易做到(見ALL CAPS COMMENTS下文):
# generate Entries for selected document fields
def generate_entries(document):
def focus_widget(event):
if event.state == 8:
event.widget.tk_focusNext().focus()
elif event.state == 9:
event.widget.tk_focusPrev().focus()
return 'break'
row = 0
for field in document.keys():
# label
ttk.Label(data_entries, text=field).grid(row=row, column=0, sticky='nw')
# widget to edit document fields
tf = Text(data_entries, name=field, wrap='word', width=20, height=2)
if row == 0: # FIRST TEXT?
data_entries.first_text = tf # REMEMBER IT.
tf.insert('1.0', document[field])
tf.grid(row=row 1, sticky='nwe', padx=0, pady=5)
tf.bind('<Tab>', focus_widget)
tf.bind('<Shift-Tab>', focus_widget)
tf.bind('<FocusIn>', lambda event: event.widget.tag_add('sel', '1.0', 'end'))
# separator
ttk.Label(data_entries).grid(row=row 2)
row = 3
然后將不再需要通過for回圈搜索它:
def focus_to_child():
try:
data_entries.first_text.focus()
except AttributeError:
pass
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/425928.html
