Python-tk。使用tab键时设置小部件焦点
我有一个GUI,左侧有一列按钮,右侧有文本输入框,页脚有一些通用GUI按钮(新建/删除/保存/退出)。左侧的按钮分别向右侧的文本输入小部件提供一组单词。我希望能够在文本输入小部件中使用control tab或control shift tab,并将焦点返回到输入文本输入小部件的按钮。我在谷歌上搜索过,也做过实验,但在使用tab键组合后,我找不到一种方法来强制聚焦某个特定的按钮Python-tk。使用tab键时设置小部件焦点,python,tkinter,Python,Tkinter,我有一个GUI,左侧有一列按钮,右侧有文本输入框,页脚有一些通用GUI按钮(新建/删除/保存/退出)。左侧的按钮分别向右侧的文本输入小部件提供一组单词。我希望能够在文本输入小部件中使用control tab或control shift tab,并将焦点返回到输入文本输入小部件的按钮。我在谷歌上搜索过,也做过实验,但在使用tab键组合后,我找不到一种方法来强制聚焦某个特定的按钮 from tkinter import * import decimal class category_rule():
from tkinter import *
import decimal
class category_rule():
def __init__(self,hi_range,low_range,word_list,rule,row):
self.hi_range = decimal.Decimal(hi_range)
self.low_range = decimal.Decimal(low_range)
self.word_list = sorted(word_list)
self.rule = rule
self.button_row = row
self.rule_button = None
self.rule_entry_window=None
def build_rules():
rule_dict = {}
rule_index = {}
words = []
rule='Fruit'
words=['Apple','Banana','Strawberry']
row=0
rule_dict[rule] = category_rule('9999.99','0.00',words,rule,row)
rule_index[row] = rule
rule = 'Vegetable'
words=['Asparagus','Brussel Sprouts','Kale','Tomato','Spinach']
row=1
rule_dict[rule] = category_rule('9999.99','0.00',words,rule,row)
rule_index[row] = rule
rule = 'Dessert'
words=['Cake','Pudding','Cookies','Pie']
row=2
rule_dict[rule] = category_rule('9999.99','0.00',words,rule,row)
rule_index[row] = rule
return rule_dict, rule_index
class rule_entry_window:
active_index = 0
active_rule = None
first_rule=None
button_row=0
rule_dict = {}
rule_index = {}
''' methods to create the window, build the frames add the widgets '''
def init_window_and_frames(self):
self.win = Tk()
self.bg_color = '#134E9C'
self.text_entry_frame = Frame(self.win, width=150, height=380, bg='#DDDECE', padx=1, pady=1, borderwidth=1)
self.button_frame_outer = Frame(self.win, width=150, height=300, bg=self.bg_color, padx=3, pady=3, borderwidth=1)
self.button_frame = Frame(self.button_frame_outer, width=150, height=300, bg = self.bg_color, padx=3, pady=3, borderwidth=1)
self.range_entry_frame = Frame(self.win, width=150, height=40, bg=self.bg_color, padx=3, pady=3, borderwidth=1)
self.footer_frame = Frame(self.win, width=480, height=30, bg=self.bg_color, padx=3, pady=3, borderwidth=1)
self.button_frame.grid(row=0,column=0,sticky='nesw')
self.button_frame_outer.grid(rowspan=2,column=0,sticky='nsew')
self.text_entry_frame.grid(row=1,column=1,sticky='s')
self.range_entry_frame.grid(row=0,column=1,sticky='new')
self.footer_frame.grid(row=2,columnspan=2,sticky='ew')
self.button_frame_outer.columnconfigure(0, minsize=200, weight=1)
self.button_frame_outer.rowconfigure(0, weight=1)
def init_rule_widgets(self):
self.scrollbar = Scrollbar(self.text_entry_frame)
self.text_entry = Text(self.text_entry_frame, width=40, height=33, wrap="word",
yscrollcommand=self.scrollbar.set, bg='#DDDECE',
borderwidth=0, highlightthickness=0)
self.text_entry.delete('1.0', END)
self.text_entry.grid(row=0,column=0,padx=2,pady=2)
self.text_entry.bind('<Control-Tab>',self.text_tab)
self.text_entry.bind('<Control-Shift-Tab>',self.text_tab)
self.scrollbar.grid(row=0,column=1,sticky='ns')
self.low_range_label = Label(self.range_entry_frame, text='Low Range',background=self.bg_color,fg='#ffffff')
self.low_range_label.grid(row=0, column=0,sticky='e')
self.low_range_entry = Entry(self.range_entry_frame, background='#DDDECE')
self.low_range_entry.grid(row=0,column=1)
self.hi_range_label = Label(self.range_entry_frame, text='High Range',background=self.bg_color,fg='#ffffff')
self.hi_range_label.grid(row=1, column=0,sticky='e')
self.hi_range_entry = Entry(self.range_entry_frame, background='#DDDECE')
self.hi_range_entry.grid(row=1,column=1)
def init_footer_buttons(self):
self.new_rule_button = Button(self.footer_frame, width=10, height=1, padx=2, pady=1, name='new button',
bg=self.bg_color, fg='#ffffff', bd=1, text='New', command=self.new_rule)
self.footer_frame.grid_columnconfigure(2, weight=0)
self.new_rule_button.grid(row=0,column=0,sticky='w')
self.delete_rule_button = Button(self.footer_frame, width=10, height=1, padx=2, pady=1, name='delete button',
bg=self.bg_color, fg='#ffffff', bd=1, text='Delete', command=self.delete_rule)
self.footer_frame.grid_columnconfigure(2, weight=0)
self.delete_rule_button.grid(row=0,column=1,sticky='w')
self.exit_button = Button(self.footer_frame, width=10, height=1, padx=2, pady=1, name='exit_button',
bg=self.bg_color, fg='#ffffff', bd=1, text='Exit', command=self.exit)
self.footer_frame.grid_columnconfigure(2, weight=1)
self.exit_button.grid(row=0,column=3,sticky='e')
self.save_button = Button(self.footer_frame, width=10, height=1, padx=2, pady=1, name='save button',
bg=self.bg_color, fg='#ffffff', bd=1, text='Save', command=self.save_rule)
self.footer_frame.grid_columnconfigure(2, weight=1)
self.save_button.grid(row=0,column=4,sticky='e')
def add_rule_button(self,rule):
self.rule_dict[rule].rule_button = Button(self.button_frame, name='b'+rule, width=30, height=1, justify=LEFT, padx=0, pady=2,
font=('Arial', 9), fg='#ffffff',bg='#134E9C', bd=0, anchor='nw',text=rule,
highlightcolor='#134E9C',command=lambda r=rule: self.fill_text_entry_window(r))
self.rule_dict[rule].rule_button.grid(row=self.rule_dict[rule].button_row,column=0,sticky='n')
self.rule_dict[rule].rule_button.bind('<Tab>',self.button_tab)
self.rule_dict[rule].rule_button.bind('<Shift-Tab>',self.button_tab)
self.rule_dict[rule].rule_button.bind('<Return>',self.focus_text_entry)
self.rule_dict[rule].rule_button.bind('<Right>',self.focus_text_entry)
self.rule_dict[rule].rule_button.bind('<Up>',self.button_uparrow)
self.rule_dict[rule].rule_button.bind('<Down>',self.button_downarrow)
''' init. call the methods to build the window, set the active button and call mainloop '''
def __init__(self):
self.init_window_and_frames()
self.init_rule_widgets()
self.init_footer_buttons()
self.rule_dict,self.rule_index = build_rules()
for rule in self.rule_dict:
self.add_rule_button(rule)
self.active_index = 0
self.active_rule = None
self.fill_text_entry_window(self.rule_index[self.active_index])
self.win.mainloop()
''' methods to process activity from the widgets '''
@classmethod
def new_rule(cls):
print('new rule - Not written yet')
@classmethod
def delete_rule(cls):
print('delete rule - Not written yet')
@classmethod
def exit(cls):
print('exit - Not written yet')
@classmethod
def save_rule(cls):
print('save - Not written yet')
''' process keyboard events'''
def button_uparrow(self,event):
if self.active_index==0:
next_rule=self.rule_index[len(self.rule_index)-1]
else:
next_rule=self.rule_index[self.active_index-1]
self.fill_text_entry_window(next_rule)
def button_downarrow(self,event):
if self.active_index+1==len(self.rule_index):
next_rule=self.rule_index[0]
else:
next_rule=self.rule_index[self.active_index+1]
self.fill_text_entry_window(next_rule)
def button_tab(self,event):
'''
make the next button active
event.state == 9 means the <shift> key is pressed. 8 is shift key is not pressed
'''
if event.state == 9:
if self.active_index==0:
next_rule=self.rule_index[len(self.rule_index)-1]
else:
next_rule=self.rule_index[self.active_index-1]
else:
if self.active_index==self.active_index==len(self.rule_index)-1:
next_rule=self.rule_index[0]
else:
next_rule=self.rule_index[self.active_index+1]
self.fill_text_entry_window(next_rule)
def focus_text_entry(self,event):
self.text_entry_frame.focus_set()
self.text_entry.focus()
def text_tab(self,event):
'''
process control-tab, control-shift-tab key combinations from text_entry widget.
Attempts to set focus back to the active button
*** doesn't work
'''
self.update_rule()
self.win.focus_set()
active_rule=self.rule_index[self.active_index]
self.footer_frame.tkraise()
self.range_entry_frame.tkraise()
''' self.button_frame_outer.tkraise() '''
self.button_frame.focus_force()
self.button_frame.tkraise()
self.button_frame_outer.tkraise()
self.button_frame.focus_force()
self.rule_dict[active_rule].rule_button.focus_force()
self.rule_dict[active_rule].rule_button.focus_set()
self.rule_dict[active_rule].rule_button.focus()
self.fill_text_entry_window(active_rule)
def fill_text_entry_window(self,selected_rule):
if self.active_rule is None:
self.active_rule = selected_rule
elif self.active_rule is not selected_rule:
self.update_rule()
''' remove highlight from the old button. Add highlight to the new one '''
self.rule_dict[self.active_rule].rule_button.config(bg='#134E9C',fg='#ffffff')
self.active_rule = self.rule_dict[selected_rule].rule
self.active_index = self.rule_dict[selected_rule].button_row
self.rule_dict[self.active_rule].rule_button.config(bg='#ffffff',fg='#134E9C')
''' clear the entry widgets and add the information for the new button '''
self.low_range_entry.delete(0,END)
self.low_range_entry.insert(0,self.rule_dict[self.active_rule].low_range)
self.hi_range_entry.delete(0,END)
self.text_entry.delete('1.0', END)
self.hi_range_entry.insert(0,self.rule_dict[self.active_rule].hi_range)
for word in self.rule_dict[self.active_rule].word_list:
self.text_entry.insert('insert', word+'\n')
''' *** attempt to set the focus on the new button. '''
self.rule_dict[self.active_rule].rule_button.focus()
self.rule_dict[self.active_rule].rule_button.focus_set()
self.rule_dict[self.active_rule].rule_button.focus_force()
def update_rule(self):
''' save any changes made to the active rule before changing to the next one '''
self.rule_dict[self.active_rule].word_list = sorted(self.text_entry.get(1.0,END).rstrip().split('\n'))
self.rule_dict[self.active_rule].hi_range = decimal.Decimal(self.hi_range_entry.get())
self.rule_dict[self.active_rule].low_range = decimal.Decimal(self.low_range_entry.get())
if __name__ == '__main__':
rule_entry_window()
从tkinter导入*
输入小数
类类别规则():
定义初始(自身、高范围、低范围、单词列表、规则、行):
self.hi\u范围=十进制.decimal(hi\u范围)
self.low\u范围=十进制.decimal(low\u范围)
self.word\u list=已排序(word\u list)
自治
self.button_row=行
self.rule_按钮=无
self.rule\u entry\u window=None
def build_规则():
规则_dict={}
规则_索引={}
单词=[]
规则‘水果’
单词=[“苹果”、“香蕉”、“草莓”]
行=0
规则[规则]=类别规则('9999.99','0.00',单词,规则,行)
规则\索引[行]=规则
规则=‘蔬菜’
单词=[‘芦笋’、‘布鲁塞尔芽’、‘甘蓝’、‘西红柿’、‘菠菜’]
行=1
规则[规则]=类别规则('9999.99','0.00',单词,规则,行)
规则\索引[行]=规则
规则=‘甜点’
单词=[‘蛋糕’、‘布丁’、‘饼干’、‘馅饼’]
行=2
规则[规则]=类别规则('9999.99','0.00',单词,规则,行)
规则\索引[行]=规则
返回规则目录,规则索引
类规则\u条目\u窗口:
活动索引=0
活动规则=无
第一条规则=无
按钮行=0
规则_dict={}
规则_索引={}
''创建窗口、构建框架和添加小部件的方法''
def初始窗口和框架(自):
self.win=Tk()
self.bg_color='#134E9C'
self.text_entry_frame=frame(self.win,width=150,height=380,bg='#DDDECE',padx=1,pady=1,borderwidth=1)
self.button\u frame\u outer=frame(self.win,宽度=150,高度=300,bg=self.bg\u颜色,padx=3,pady=3,borderwidth=1)
self.button\u frame=frame(self.button\u frame\u外部,宽度=150,高度=300,bg=self.bg\u颜色,padx=3,pady=3,borderwidth=1)
self.range\u entry\u frame=frame(self.win,宽度=150,高度=40,bg=self.bg\u颜色,padx=3,pady=3,borderwidth=1)
self.footer\u frame=frame(self.win,宽度=480,高度=30,bg=self.bg\u颜色,padx=3,pady=3,borderwidth=1)
self.button\u frame.grid(行=0,列=0,sticky='nesw')
self.button\u frame\u outer.grid(行span=2,列=0,sticky='nsew')
self.text\u entry\u frame.grid(行=1,列=1,sticky='s')
self.range\u entry\u frame.grid(行=0,列=1,sticky='new')
self.footer\u frame.grid(行=2,列span=2,sticky='ew')
self.button\u frame\u outer.columnconfigure(0,minsize=200,weight=1)
self.button\u frame\u outer.rowconfigure(0,权重=1)
def init_rule_小部件(自):
self.scrollbar=滚动条(self.text\u entry\u frame)
self.text\u entry=text(self.text\u entry\u框架,宽度=40,高度=33,wrap=“word”,
yscrollcommand=self.scrollbar.set,bg='#DDDECE',
borderwidth=0,highlightthickness=0)
self.text\u entry.delete('1.0',END)
self.text_entry.grid(行=0,列=0,padx=2,pady=2)
self.text\u entry.bind(“”,self.text\u选项卡)
self.text\u entry.bind(“”,self.text\u选项卡)
self.scrollbar.grid(行=0,列=1,sticky='ns')
self.low_range_label=label(self.range_entry_frame,text='low range',background=self.bg_color,fg='#ffffffff')
self.low\u range\u label.grid(行=0,列=0,sticky='e')
self.low_range_entry=entry(self.range_entry_frame,background='#DDDECE')
self.low\u range\u entry.grid(行=0,列=1)
self.hi_range_label=label(self.range_entry_frame,text='High range',background=self.bg_color,fg='#ffffffff')
self.hi\u range\u label.grid(行=1,列=0,sticky='e')
self.hi_range_entry=entry(self.range_entry_frame,background='#DDDECE')
self.hi\u range\u entry.grid(行=1,列=1)
def初始页脚按钮(自身):
self.new\u rule\u button=button(self.footer\u框架,宽度=10,高度=1,padx=2,pady=1,name='new button',
bg=self.bg_颜色,fg='#ffffff',bd=1,text='New',command=self.New_规则)
self.footer\u frame.grid\u column配置(2,权重=0)
self.new\u rule\u button.grid(行=0,列=0,sticky='w')
self.delete\u rule\u button=按钮(self.footer\u框架,宽度=10,高度=1,padx=2,pady=1,name='delete button',
bg=self.bg_color,fg='#ffffff',bd=1,text='Delete',command=self.Delete_规则)
self.footer\u frame.grid\u column配置(2,权重=0)
self.delete\u rule\u button.grid(行=0,列=1,sticky='w')
self.exit_button=按钮(self.footer_框架,宽度=10,高度=1,padx=2,pady=1,name='exit_button',
bg=self.bg_color,fg='#ffffff',bd=1,text='Exit',command=self.Exit)
self.footer\u frame.grid\u column配置(2,权重=1)
self.exit_button.grid(行=0,列=3,粘滞=e')
self.save_button=按钮(self.footer_框架,宽度=10,高度=1,padx=2,pady=1,name='save button',
bg=self.bg_颜色,fg='#ffffff',bd=1,text='Save',command=self.Save_规则)
self.footer\u frame.grid\u column配置(2,权重=1)
self.save_button.grid(行=0,列=4,sticky='e')
def添加规则按钮(自身、规则):
self.rule\u dict[rule].rule\u button=button(self.button\u框架,name='b'+规则,宽度=30,高度=1,对齐=LEFT,padx=0,pady=2,
font=('Arial',9),fg='ffffff',bg='134E9C',bd=0,anchor='nw',text=rule,
highlightcolor='#134E9C',command=lambda r=rule:self.fill\u text\u en
def text_tab(self, event):
# ... code ...
return "break"