Skip to main content
 首页 » 编程设计

python之在 Tkinter 中更改帧的 Tab 键顺序

2025年05月04日20kevingrace

总结

如何提升 (tk_raise) 一个框架中包含的 Tab 键顺序小部件高于另一个框架中包含的小部件,该框架首先创建?

完整版

我有一个 Tkinter 表单,为此我将多个小部件分组到框架中,然后使用网格布局将框架定位到窗口中。在我的特定用例中,框架是从 ttk.Frame 派生的类,但这对这个问题没有任何影响,因为它对这个问题的表单行为没有影响。

对于我的用例,在循环中创建多个帧是有意义的,以避免代码重复。正如预期的那样,小部件的 Tab 键顺序是它们的创建顺序。然而,在这种情况下,表单的自然流程是按以下顺序在小部件之间切换:[0, 1, 2, 3, 4, 10, 11, 12, 5, 6, 7, 8, 9](参见下面的 MCVE)。

在包含小部件 10-12 的框架上执行 lift 不会更改 Tab 键顺序。但是,对小部件 10-12 进行单独提升会生成以下异常:

_tkinter.TclError: can't raise ".tabtest.frame_2.widget_10" above ".tabtest.frame_1.widget_5 

这应该是可行的,但是怎么做呢?

编辑

如评论(下方)所述,乍一看这似乎是问题 "How to set the tab order in a tkinter application?" 的重复.在提交我的之前,我审查了这个问题。然而,answer这个问题特别提到了在单个框架内为小部件设置选项卡顺序。当我运行答案中包含的示例时,它按预期工作。但是,将其应用于我的用例时:

  • 尝试抬起框架不会导致选项卡行为发生变化。

  • 尝试提升框架中包含的各个小部件会产生上述错误。

MCVE

使用 Python 3.4 编写。

import tkinter as tk 
from tkinter import ttk 
 
class TabTest(ttk.Frame): 
    def __init__(self, master, *args, **kwargs): 
        super().__init__(master, *args, **kwargs) 
 
        # Remove row/column weights. 
        for i in range(50): 
            self.rowconfigure(i, weight=0) 
            self.columnconfigure(i, weight=0) 
 
        # Entry fields. 
        frames = [] 
        entries = [] 
 
        x = 0 
        for i in range(2): 
            f = ttk.Frame(self, takefocus=0, name='frame_{}'.format(i)) 
            for j in range(5): 
                e = ttk.Entry(f, name='widget_{}'.format(x)) 
                entries.append(e) 
                e.insert(tk.END, 'Widget {}'.format(x)) 
                e.pack(side='top', anchor='w') 
                x += 1 
 
            frames.append(f) 
 
        # Buttons 
        buttons = [] 
        f = ttk.Frame(self, takefocus=0, name='frame_2') 
        for i in range(3): 
            b = ttk.Button(f, text='Widget {}'.format(x), 
                           name='widget_{}'.format(x))   
            buttons.append(b) 
            b.pack(fill='x') 
            x += 1 
 
        frames.append(f) 
 
        frames[0].grid(row=0, column=0, rowspan=5, columnspan=2, 
                       padx=2, pady=2, sticky='news') 
        frames[2].grid(row=0, column=2, rowspan=5, columnspan=2, 
                       padx=2, pady=2, sticky='news') 
        frames[1].grid(row=0, column=4, rowspan=5, columnspan=2, 
                       padx=2, pady=2, sticky='news') 
 
        frames[2].lift()  # No difference in tab order. 
#         for btn in buttons: 
#             btn.lift(entries[5])  # Generates exception: _tkinter.TclError: can't raise ".tabtest.frame_2.widget_10" above ".tabtest.frame_1.widget_5 
 
        self.buttons = buttons 
        self.frames = frames 
        self.entries = entries 
 
        self.pack(fill='both') 
        root = self._root() 
        root.update() 
        root.minsize(root.winfo_width(), root.winfo_height()) 
 
 
 
def main(): 
    root = tk.Tk() 
    app = TabTest(root, name='tabtest') 
    root.mainloop() 
 
 
 
if __name__ == '__main__': 
    main() 

请您参考如下方法:

您可以调用 lift() 而不为所有帧按您希望的顺序调用参数:

for idx in [0,2,1]: 
    frames[idx].lift()