Tkinter高级编程:掌握类与面向对象设计

这是文章《高级Tkinter:使用类进行操作》的第1部分(共4部分)。

今天,我们将深入探讨如何在Tkinter中使用类。如果你之前接触过Tkinter,你可能知道它提供了丰富的GUI功能来创建应用程序。

然而,在实际开发中,你很快会意识到Tkinter的复杂性远超表面。它隐藏着许多强大的功能,其中之一就是如何在模块中有效地利用类。

Tkinter模块安装

Tkinter是Python标准库的一部分,因此无需额外安装。但是,本文将涉及Tkinter的高级用法,建议读者先阅读Tkinter的基础系列教程。

在继续之前,请务必阅读以下Tkinter基础教程:

如果你已经完成了基础教程,那么让我们开始使用Tkinter模块吧!

为了使用类,我们需要导入Tkinter模块:

# 导入Tkinter模块
import tkinter as tk

# 用于GUI样式设计
from tkinter import ttk

为了方便起见,我们还将单独导入ttk包,它提供了更现代的GUI组件。

在Tkinter中利用类进行开发

现在,让我们了解如何在Tkinter中运用类。我们将构建一个简单的应用程序,其工作方式如下:

首先,创建一个根窗口,并在其上放置一个独立的框架。为了模拟一个带有不同“窗口”的应用程序,我们还将实现一个功能,允许用户在不同的框架之间切换。

这会给用户一种错觉,认为他们正在被重定向到不同的窗口或标签页,但实际上只是在不同的框架之间进行切换。我们将使用的框架包括主页面、侧边页面和完成页面。

我们将使用show_frame()方法来实现框架之间的切换。

开始编码:创建基类

让我们创建一个基类,所有其他类或窗体都将从这个基类继承,作为应用程序的起点。

# 允许从Tk类扩展
class testClass(tk.Tk):

tk.Tk类继承使我们能够使用Tk()类中提供的所有组件和功能。

1. 类的初始化

这是文章《高级的Tkinter:使用类进行操作》的第2部分(共4部分)。

内容片段:为了初始化类,我们使用__init__函数。这样可以创建一个在我们从类中生成对象时自动运行的方法。

以类似的方式,我们也通过tk.Tk.__init__初始化类。

import tkinter as tk
from tkinter import ttk

class windows(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        # 为窗口添加标题
        self.wm_title("测试应用程序")

        # 创建一个框架并将其分配给容器
        container = tk.Frame(self, height=400, width=600)
        # 指定框架在根窗口中的打包区域
        container.pack(side="top", fill="both", expand=True)

        # 使用grid配置容器的位置
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        # 我们现在将创建一个框架字典
        self.frames = {}
        # 我们稍后会创建框架本身,但现在先将组件添加到字典中。
        for F in (MainPage, SidePage, CompletionScreen):
            frame = F(container, self)

            # windows类作为框架的根窗口。
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        # 使用方法切换框架
        self.show_frame(MainPage)

2. 创建一种切换视图框架的方法。

这是文章《高级的Tkinter:使用类进行操作》的第3部分(共4部分)。

内容片段: 现在我们已经创建了__init__方法,并指定了要使用的框架,我们可以创建一个方法来切换我们正在查看的框架。

    def show_frame(self, cont):
        frame = self.frames[cont]
        # 将当前框架提升到顶部
        frame.tkraise()

3. 为框架创建多个类。现在,我们创建不同的类作为框架,并通过 show_frame() 方法进行切换。

class MainPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="主页")
        label.pack(padx=10, pady=10)

        # 我们使用 switch_window_button 来调用 show_frame() 方法作为 lambda 函数
        switch_window_button = tk.Button(
            self,
            text="前往侧边页",
            command=lambda: controller.show_frame(SidePage),
        )
        switch_window_button.pack(side="bottom", fill=tk.X)


class SidePage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="这是侧边页")
        label.pack(padx=10, pady=10)

        switch_window_button = tk.Button(
            self,
            text="前往完成界面",
            command=lambda: controller.show_frame(CompletionScreen),
        )
        switch_window_button.pack(side="bottom", fill=tk.X)


class CompletionScreen(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="完成界面,我们做到了!")
        label.pack(padx=10, pady=10)
        switch_window_button = ttk.Button(
            self, text="返回菜单", command=lambda: controller.show_frame(MainPage)
        )
        switch_window_button.pack=(side="bottom", fill=tk.X)

如果你注意到了的话,这些类是通过 self.frames 变量添加到主类中的。

我将保留将类实现的命令放在 __name__ == "__main__" 中,但你也可以直接使用它。

if __name__ == "__main__":
    testObj = windows()
    testObj.mainloop()

继续前进

我们现在已经完成了定义类和方法的步骤,可以运行这个脚本了。

这应该会弹出一个小窗口,你只需点击一个按钮即可在不同的帧(frame)之间进行切换。

更进一步,你甚至可以在应用程序顶部的菜单栏中实现切换帧的功能。

结论

在Tkinter模块中使用类进行开发,为处理和创建新应用程序打开了许多机会。

我们今天处理了相当多的代码,为了确保我们都理解一致,以下是核心要点!

如果你希望查看一个现成的例子,请看看我的项目“艾森票务”(Eisen Ticketing),它实现了许多Tkinter的特性,包括类,并且使用SQLite3数据库运行。

参考资料

  • Tkinter 文档
  • Tkinter 类
bannerAds