更改Tkinter中帧的Tab键顺序

时间:2017-10-25 17:09:45

标签: python python-3.x tkinter

摘要

我如何lifttk_raise)首先创建的另一个框架中包含的窗口小部件上方的一个框架中包含的Tab键顺序窗口小部件?

完整版

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

对于我的用例,在循环中创建多个帧是有意义的,以避免代码重复。正如所料,窗口小部件的Tab键顺序是创建它们的顺序。但是,在这种情况下,表单的自然流程是按照以下顺序在窗口小部件之间进行选项卡:[0, 1, 2, 3, 4, 10, 11, 12, 5, 6, 7, 8, 9](请参阅下面的MCVE)。

对包含小部件10-12的框架执行lift不会更改标签顺序。但是,对小部件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()

2 个答案:

答案 0 :(得分:3)

你可以按照你想要的顺序为所有帧调用lift()而没有参数:

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

答案 1 :(得分:2)

您可以撤销逻辑,并将lower应用于frames[1]

frames[1].lower()

而不是frames[2].lift(frames[1])