在 Tkinter 中创建向导

Posted

技术标签:

【中文标题】在 Tkinter 中创建向导【英文标题】:Creating a wizard in Tkinter 【发布时间】:2017-05-11 00:27:58 【问题描述】:

我正在 Tkinter 中创建一个向导。几乎每个步骤都应该与导航和取消按钮具有相同的页脚。我怎样才能做到这一点?我应该创建一个框架吗?一般来说,是否应该将所有步骤创建为不同的框架?

【问题讨论】:

不是很清楚,您能否详细说明一下您的向导的结构和界面是什么样的,以及页脚的具体作用是什么?按钮的功能从它们的标题看来已经很明显了。 见Switch between two frames in tkinter。它使用Frame 创建Pages - 您可以以相同的方式使用Frame 或使用Frame 创建带有按钮的小部件(并放置其他元素),然后使用此小部件构建Pages 【参考方案1】:

这个问题的答案与Switch between two frames in tkinter 没有太大区别。唯一显着的区别是您希望底部有一组永久按钮,但那里没有什么特别的事情要做 - 只需创建一个带有一些按钮的框架,作为包含各个页面(或步骤)的小部件的兄弟。

我建议为从Frame 继承的每个向导步骤创建一个单独的类。然后只需删除当前步骤的框架并显示下一步的框架即可。

例如,一个步骤可能看起来像这样(使用 python 3 语法):

class Step1(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        header = tk.Label(self, text="This is step 1", bd=2, relief="groove")
        header.pack(side="top", fill="x")

        <other widgets go here>

其他步骤在概念上是相同的:一个带有一堆小部件的框架。

您的主程序或您的向导类将根据需要实例化每个步骤,或者提前将它们全部实例化。然后,您可以编写一个以步数为参数的方法,并相应地调整 UI。

例如:

class Wizard(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        self.current_step = None
        self.steps = [Step1(self), Step2(self), Step3(self)]

        self.button_frame = tk.Frame(self, bd=1, relief="raised")
        self.content_frame = tk.Frame(self)

        self.back_button = tk.Button(self.button_frame, text="<< Back", command=self.back)
        self.next_button = tk.Button(self.button_frame, text="Next >>", command=self.next)
        self.finish_button = tk.Button(self.button_frame, text="Finish", command=self.finish)

        self.button_frame.pack(side="bottom", fill="x")
        self.content_frame.pack(side="top", fill="both", expand=True)

        self.show_step(0)

    def show_step(self, step):

        if self.current_step is not None:
            # remove current step
            current_step = self.steps[self.current_step]
            current_step.pack_forget()

        self.current_step = step

        new_step = self.steps[step]
        new_step.pack(fill="both", expand=True)

        if step == 0:
            # first step
            self.back_button.pack_forget()
            self.next_button.pack(side="right")
            self.finish_button.pack_forget()

        elif step == len(self.steps)-1:
            # last step
            self.back_button.pack(side="left")
            self.next_button.pack_forget()
            self.finish_button.pack(side="right")

        else:
            # all other steps
            self.back_button.pack(side="left")
            self.next_button.pack(side="right")
            self.finish_button.pack_forget()

函数nextbackfinish 的定义非常简单:只需调用self.show_step(x),其中x 是应显示的步骤编号。例如,next 可能如下所示:

def next(self):
    self.show_step(self.current_step + 1)

【讨论】:

谢谢,1)页脚,几乎所有步骤都应该共享? 2) 我应该在哪里创建root = Tk() @Jodooomi:“页脚”是self.button_frame。您可以在其中放置您想要的任何内容,或创建多个页脚或页眉或您想要的任何内容。您可以像往常一样随时随地创建根窗口。 是的,我通常应该在哪里创建根目录,你能告诉我吗?在“主要”中? 我不明白。为什么 Wizard 是从 Frame 继承的?是否应该再从 Tk 继承一个主类?在您给我的链接中,类层次结构不同,不适用于您的解决方案。这就是为什么我要求你给我一个如何在你的解决方案中初始化 root 的例子。 @Jodooomi:为什么从框架继承向导?没有特别的原因。我发现这是一种方便的模式。 是否应该再继承一个从 Tk 继承的主类? 绝对不是。 “在你给我的链接中,类层次结构不同,不适用于你的解决方案。” 你为什么这么说?它完全相同,只是类的名称不同。只需将MainApplication 替换为Wizard(反之亦然)。【参考方案2】:

我建议使用一个带有按钮的主窗口,并将其余的小部件放在不同的标签框架中,这些标签框架会在按钮执行不同的功能时出现和消失

【讨论】:

以上是关于在 Tkinter 中创建向导的主要内容,如果未能解决你的问题,请参考以下文章

如果在函数中创建,为啥 Tkinter 图像不显示?

如何在 Tkinter 中创建带有标签的超链接?

在 tkinter 类中创建一个切换按钮

如何在 tkinter 中创建日期选择器?

在 TKinter 窗口中创建图形?

在 tkinter 中创建“填充”命令