Tkinter 面向对象框架《二》

news2024/11/26 13:50:57

一、说明

        Tkinter 教程 » 开发完整的 Tkinter 面向对象应用程序开发完整的 Tkinter 面向对象应用程序。

        即使OOP的高手,也未必对面向对象全部掌握。至于 Tkinter的OOP编程,其实高手们也是在摸索实践中。 为了面向对象和Tkinter参与本教程。如果你来这里纯粹是为了学习面向对象编程,那很好。

二、第一个实验演示

        在本教程中,您将学习如何开发一个完整的 Tkinter 面向对象的应用程序。您需要将温度转换器应用程序转换为使用面向对象编程方法的新应用程序:

        首先,定义一个名为TemperatureConverter .该类有一个静态方法,用于将温度从华氏度转换为摄氏度:

import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showerror

class TemperatureConverter:
    @staticmethod
    def fahrenheit_to_celsius(f):
        return (f - 32) * 5 / 9

        其次,定义一个继承自 ttk.Frame 类的 ConverterFrame 类。 ConverterFrame 类将负责创建小部件和处理事件:


class ConverterFrame(ttk.Frame):
    def __init__(self, container):
        super().__init__(container)
        # field options
        options = {'padx': 5, 'pady': 5}

        # temperature label
        self.temperature_label = ttk.Label(self, text='Fahrenheit')
        self.temperature_label.grid(column=0, row=0, sticky=tk.W, **options)

        # temperature entry
        self.temperature = tk.StringVar()
        self.temperature_entry = ttk.Entry(self, textvariable=self.temperature)
        self.temperature_entry.grid(column=1, row=0, **options)
        self.temperature_entry.focus()

        self.convert_button = ttk.Button(self, text='Convert')
        self.convert_button['command'] = self.convert
        self.convert_button.grid(column=2, row=0, sticky=tk.W, **options)

        # result label
        self.result_label = ttk.Label(self)
        self.result_label.grid(row=1, columnspan=3, **options)

        # add padding to the frame and show it
        self.grid(padx=10, pady=10, sticky=tk.NSEW)

    def convert(self):
        """  Handle button click event
        """
        try:
            f = float(self.temperature.get())
            c = TemperatureConverter.fahrenheit_to_celsius(f)
            result = f'{f} Fahrenheit = {c:.2f} Celsius'
            self.result_label.config(text=result)
        except ValueError as error:
            showerror(title='Error', message=error)

工作原理:

  • 需要一个容器,因此,它的方法有参数。ConverterFrame__init__()container
  • 在类的方法中,调用其超类的方法。__init__()ConverterCFrame__init__()
  • 将小部件分配给对象,以便可以在类的其他方法中引用它们。selfConverterFrame
  • 将按钮的选项分配给方法。commandconvertself.convert

第三,定义一个继承自该类的类:Apptk.Tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('Temperature Converter')
        self.geometry('300x70')
        self.resizable(False, False)

最后,从块引导应用程序:if __name__ == "__main__"

if __name__ == "__main__":
    app = App()
    ConverterFrame(app)
    app.mainloop()

把它们放在一起:

import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showerror


class TemperatureConverter:
    @staticmethod
    def fahrenheit_to_celsius(f):
        return (f - 32) * 5 / 9


class ConverterFrame(ttk.Frame):
    def __init__(self, container):
        super().__init__(container)
        # field options
        options = {'padx': 5, 'pady': 5}

        # temperature label
        self.temperature_label = ttk.Label(self, text='Fahrenheit')
        self.temperature_label.grid(column=0, row=0, sticky=tk.W, **options)

        # temperature entry
        self.temperature = tk.StringVar()
        self.temperature_entry = ttk.Entry(self, textvariable=self.temperature)
        self.temperature_entry.grid(column=1, row=0, **options)
        self.temperature_entry.focus()

        self.convert_button = ttk.Button(self, text='Convert')
        self.convert_button['command'] = self.convert
        self.convert_button.grid(column=2, row=0, sticky=tk.W, **options)

        # result label
        self.result_label = ttk.Label(self)
        self.result_label.grid(row=1, columnspan=3, **options)

        # add padding to the frame and show it
        self.grid(padx=10, pady=10, sticky=tk.NSEW)

    def convert(self):
        """  Handle button click event
        """
        try:
            f = float(self.temperature.get())
            c = TemperatureConverter.fahrenheit_to_celsius(f)
            result = f'{f} Fahrenheit = {c:.2f} Celsius'
            self.result_label.config(text=result)
        except ValueError as error:
            showerror(title='Error', message=error)


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('Temperature Converter')
        self.geometry('300x70')
        self.resizable(False, False)


if __name__ == "__main__":
    app = App()
    ConverterFrame(app)
    app.mainloop()

在本教程中,您学习了如何开发一个完整的面向对象的 Tkinter 应用程序。

三、Tkinter 面向对象编程速成班

3.1 使用OOP设计Tlinter的多窗口应用

        对于那些不熟悉或困惑于面向对象编程的人来说,你并不孤单。即使是使用它的人有时通常也无法完全了解其内部工作原理。我不认为自己是 OOP 专家,特别是因为我很少使用它,但我知道它足以知道从长远来看,它将帮助我们的 Tkinter 应用程序,我可以为你们分享我所知道的好人!

        因此,面向对象编程是一种编程范式,或者更确切地说:一种结构。就是这样。它只是我们用来构建程序的结构。Python 通常被视为一种纯粹的脚本语言,但实际上它从根本上说是一种 OOP 语言。

        在 OOP 中,你基本上陈述了程序的结构,而你的类从字面上返回“对象”,这就是为什么它被称为面向“对象”的原因。这些对象充当类的“实例”。在我们举个例子之前,我想说的就是这些。我认为一个实际的例子对帮助学习有很长的路要走,所以让我们开始吧!

        我将分块分享代码,解释每个步骤。如果你迷路了,我会在最底部发布这个系列代码的“完整”版本,所以不要害怕!

import tkinter as tk

class SeaofBTCapp(tk.Tk):
		

        我们从简单地将 tkinter 导入为 tk 开始。如果您使用的是 Python 2,请记住 tkinter 称为 Tkinter。

        之后,我们定义我们的SeaofBTCapp类,并传递tk。Tk 看起来就是我们所知道的参数。首先,类根本不需要任何括号。我可以做类SeaofBTCapp:这不会是语法错误。那么什么是tk。那么Tk呢?当你在括号中看到这样的内容时,这意味着该类是从另一个类继承而来的。在我们的例子中,我们继承了 tk 的所有内容。Tk 类。把它想象成你如何导入模块来使用它们。这基本上就是你继承时发生的事情,只是在本地类级别。

        现在,在我们的class中,我们有:

    def __init__(self, *args, **kwargs):
		

        虽然不是必需的,但您通常会将类中的第一个“函数”视为__init__。首先,这些不是函数,即使它们的行为就像函数一样。它们实际上被称为“方法”,__init__是一种非常特殊的方法,因为这种方法总是运行的。Init 缺少初始化,并且只要调用该类,您在此处放入的任何内容都将始终运行。其他方法仅在您专门调用它们运行时才会运行。可以将其视为启动时在计算机上运行的各种启动过程。您希望某些事情始终在计算机打开时启动。您希望鼠标驱动程序联机,需要键盘工作,希望图形驱动程序将桌面抽出,等等。您可能拥有的其他程序,您只希望它们在您单击其图标时启动。这些方法与其他方法类似。

        现在我们已经知道了,我们看到 “init” 中的第一个参数是 “self”。这纯粹是出于标准,实际上不是必需的。你不需要它,你可以完全称它为别的东西,比如“墨西哥卷饼”。称其为“自我”是个好主意,因为这是公认的做法。但是,如果您的目标是混淆,则可以重命名它。因此,self 只是所有类方法的第一个参数。然后你看,我们称它们为“*args”和“**kwargs”。

        就像“self”一样,实际上输入“args”和“kwargs”是没有必要的,这是技巧的星号。添加“args”和“kwargs”是很常见的。那么这些是什么呢?这些参数用于通过方法传递变量、未知数量的参数。它们之间的区别在于 args 用于传递非关键字参数,其中 kwargs 是关键字参数(因此在名称中进行网格划分以使其成为 kwargs)。参数是典型参数。Kwargs,基本上是字典。你可以把kwargs看作是正在传递的词典。

所以,从理论上讲,你可以有一个类似于 def example(farg, *, **) 的方法或函数。Fargs 是必需的,正如您现在可能知道的那样,如果没有为它们分配任何内容,它们将抛出错误。

接下来,我们在 def __init___下有以下行:

        tk.Tk.__init__(self, *args, **kwargs)
		

在这里,我们初始化继承的类。现在来快速查看一些特定于 Tkinter 的代码:

        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
		

        我们已经定义了这个容器,它将填充一堆帧,以便稍后访问。

        接下来,我们有 container.pack。在 Tkinter 中,有两种主要方法可以填充和定位您在框架中创建的小部件。一种方式是包装,另一种是网格。根据您的需求和您对什么感到满意,您可能会比另一个更多地使用一个。在大多数情况下,我发现网格让我对应用程序有了最大的控制权。网格允许您创建一种网格,用于定向事物在应用程序中的位置。打包允许一些控制,但对我来说,主要是感觉你只是把东西塞进枕套里,只是尽力选择一边,但它并不总是按预期工作。

        grid_configure选项只是我们早期设置的一些简单配置设置。

        self.frames = {}
        frame = StartPage(container, self)
        self.frames[StartPage] = frame
		

        我们预定义了一个字典,该字典目前是空的。还记得之前关于字典和 kwargs 的事情吗?你认为这本词典会去哪里?

        接下来,我们定义框架是什么。最终,我们将用一堆可能的帧打包 self.frames,“顶部”帧是当前帧。现在,我们只有一个页面,即“StartPage”(尚未定义)。

        接下来,仍然在__init__中,我们有:

        frame.grid(row=0, column=0, sticky="nsew")
		

        在这里,我们使用网格来放置我们的小部件。对于此小组件,行和列均为 0。然后我们有粘性。“新南威尔士州”对应于方向(北、南、东、西)。粘性的概念就像对齐一样,拉伸略有变化。因此,如果您将某些内容对齐 e,那么小部件将在右侧。如果你说 sticky=“ew”,那么小部件将从左侧延伸到右侧。如果您像我们一样粘住“nsew”,那么将鼓励小部件填充分配的整个空间。

        self.show_frame(StartPage)
		

        最后,我们调用 show_frame,这是一个我们尚未定义的方法,但它将用于带来我们选择的框架,因此让我们创建该方法:

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()
		

        另一种方法,带有 self 和控制器的 cont 参数。

        然后,我们将 frame 定义为 self.frame(即上面的字典),然后是控制器,它是字典中值的关键,即我们的框架。

        最后,我们执行 frame.tkraise(),它会将我们的框架带到顶部供用户查看。

太好了,我们的后端基本上都准备好了。现在让我们制作起始页。

class StartPage(tk.Frame):

    def __init__(self, parent, controller):

        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="This is the start page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)
		

        在这里,我们有继承自 tk 的 StartPage 类。框架。然后我们有一个典型的__init__,其初始化为 tk。框架也是如此。

        然后我们定义一个标签小部件,即 Tkinter 代码。你会看到,对于“字体”,我们称之为Large_Font。这是一个常量,我们将把它放在应用程序的顶部。

        因此,在调用要导入的 tkinter 后,添加:

        LARGE_FONT= ("Verdana", 12)
		

        现在,回到我们的 StartPage 类。

        我们使用的是 .pack,在 y 和 x 上有一些填充。填充只是在事物的边缘添加一些空白区域,以帮助事物看起来不那么杂乱。

        最后,在脚本的最后,我们只需要:

app = SeaofBTCapp()
app.mainloop()
		

        App 是 SeaofBTCapp 类的对象,然后我们运行 .mainloop(),这是一个 tkinter 功能,但由于继承,我们可以使用它。

        大功告成!继续运行脚本,您应该看到:

Python 中的 Tkinter GUI 教程

3.2 完整脚本 

import tkinter as tk

LARGE_FONT= ("Verdana", 12)

class SeaofBTCapp(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)

        container.pack(side="top", fill="both", expand = True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        frame = StartPage(container, self)

        self.frames[StartPage] = frame

        frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Start Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

app = SeaofBTCapp()
app.mainloop()

四、总结

        我承认,在这一点上,可能会觉得 Tkinter 将非常难用,我们本可以更轻松地创建我们刚刚创建的窗口。我想强调的是,我们在这里所做的主要是为扩张奠定一些基础。我们现在有一个后端,可以很容易地让我们添加越来越多的页面,因此,在未来,添加页面就像创建另一个类一样简单,就像 StartPage 一样,向它添加导航,然后你就设置好了。

参考资料:

开发完整的 Tkinter 面向对象应用程序 (pythontutorial.net)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1287315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ArcGIS Pro】探索性插值无法覆盖所需shp范围

做个小记录自用,实际不准。 1 看看就行 pro插值 看看过程就行。有详细过程,类似tutorial https://learn.arcgis.com/zh-cn/projects/interpolate-temperatures-using-the-geostatistical-wizard/ 2 注意用投影坐标系 wgs84转投影坐标系 https://blog…

关于“你对SpringCloud的理解”

看看普通人和高手是如何回答这个问题的? 普通人 Spring Cloud 是一套微服务解决方案 它包括配置中心、RPC 通信、服务注册、服务熔断等组件 高手 Spring Cloud 是一套 分布式微服务的技术解决方案 它提供了快速构建分布式系统的 常用的一些组件 比如说配置…

腾讯云服务器上安装nginx部署前端

1.宝塔面板 安装nginx 2.配置nginx

使用激光雷达(LiDAR)和相机进行3D物体跟踪

使用相机和激光雷达进行时间到碰撞(TTC)计算 在我的先前文章中,我介绍了通过检测关键点和匹配描述符进行2D特征跟踪的主题。在本文中,我将利用这些文章中的概念,以及更多的内容,开发一个软件流水线&#xf…

【ArcGIS Pro微课1000例】0050:如何清除坐标系信息

文章目录 一、目的二、方法1. 使用【定义投影】工具2. 清除数据的投影信息3. 删除坐标文件 一、目的 地理信息数据的坐标系是将地理信息数据进行融合、叠加、分析的重要数学框架,而其描述信息是非常重要的元数据,涉及整个国家的测绘坐标系统&#xff0c…

华清远见嵌入式学习——C++——作业6

作业要求&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;class Animal { public:virtual void perform() 0;};class Lion:public Animal { private:string foods;string feature; public:Lion(){}Lion(string foods,string feature):foods(foo…

1_控制系统总体结构

1、总体结构 控制系统结构图&#xff1a; 黑色块为参数、黄色块为计算模块 1.1 其中参数含义 车辆属性参数&#xff1a; 参数含义 C α f C_{\alpha f} Cαf​自行车模型总轮胎侧偏刚度&#xff08;前轮&#xff09; C α r C_{\alpha r} Cαr​自行车模型总轮胎侧偏刚度&a…

Docker镜像构建:技术深度解析与实践

目录 ​编辑 一、Docker镜像基础与优化 Docker镜像概念 Dockerfile详解 层级缓存机制 二、镜像构建的高级技术 多阶段构建 安全性考量 三、构建性能优化与调试 性能优化策略 构建过程调试 四、代码实战 实例&#xff1a;构建优化的Docker镜像 调试技巧 实例&…

openlayers地图使用---跟随地图比例尺动态标绘大小的一种方式

openlayers地图使用—跟随地图比例尺动态标绘大小的一种方式 预期&#xff1a;随着地图比例尺放大缩小&#xff0c;地图上的标绘随着变化尺寸 结果图 页面元素 <script src"https://cdn.bootcdn.net/ajax/libs/openlayers/8.1.0/dist/ol.min.js"></script…

SpringBoot : ch12 多模块配置YAML文件

前言 当您使用SpringBoot框架进行项目开发时&#xff0c;通常需要配置一些参数和属性。在实际开发中&#xff0c;可能需要将这些配置参数分成多个不同的YAML文件&#xff0c;并将它们组织到不同的模块中。这样可以方便管理和维护配置文件&#xff0c;并且可以避免配置文件的冲…

智能优化算法应用:基于瞬态优化算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于瞬态优化算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于瞬态优化算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.瞬态优化算法4.实验参数设定5.算法结果6.参考…

java8 升级 java11

1.安装java11 1.1 安装参考 ​​​​​​LINUX安装JDK_liunx上安装ocean-CSDN博客 1.2 检查 java -version 2.Maven 项目pom文件修改 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEnc…

12.05

以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系&#xff1a; 比喻&#xff1a;动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴子等。现在&#xff0c;动物园里有一位讲解员&…

【JavaWeb】前端工程化(VUE3)

前端工程化&#xff08;VUE3&#xff09; 文章目录 前端工程化&#xff08;VUE3&#xff09;一、概述二、ECMA6Script2.1 es6的变量和模板字符串2.2 es6的解构表达式2.3 es6的箭头函数2.4 rest和spread2.5 es6的对象创建和拷贝2.6 es6的模块化处理 三、前端工程化环境搭建3.1 N…

玩转大数据7:数据湖与数据仓库的比较与选择

1. 引言 在当今数字化的世界中&#xff0c;数据被视为一种宝贵的资源&#xff0c;而数据湖和数据仓库则是两种重要的数据处理工具。本文将详细介绍这两种工具的概念、作用以及它们之间的区别和联系。 1.1. 数据湖的概念和作用 数据湖是一个集中式存储和处理大量数据的平台&a…

Java-宋红康-(课P132)-多线程的概念

b站视频&#xff1a; https://www.bilibili.com/video/BV1PY411e7J6?p132&vd_source969a2f5c0c775c9626d7d7abe1828db0 目录 1.1 概述 1.2 程序、进程与线程 1.3 进程与线程的关系 1.4 线程调度 1.5 多线程程序的优点 1.6 补充概念-单核CPU和多核CPU 1.1 概述 我们…

Oracle merge into语句(merge into Statement)

在Oracle中&#xff0c;常规的DML语句只能完成单一功能&#xff0c;&#xff0c;例如insert/delete/update只能三选一&#xff0c;而merge into语句可以同时对一张表进行更新/插入/删除。 目录 一、基本语法 二、用法示例 2.1 同时更新和插入 2.2 where子句 2.3 delete子句 2.4…

Python神器解析时间序列数据:数据分析者必读

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 时间序列数据是在许多领域中都至关重要的数据类型&#xff0c;它涵盖了一系列按时间顺序排列的数据点。Python作为一种强大的数据分析工具&#xff0c;提供了许多库和工具&#xff0c;能够有效地处理、分析和可视…

掌握Python Pingouin:数据统计新利器解析!

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Pingouin库基于pandas、scipy和statsmodels&#xff0c;为用户提供了执行常见统计分析的功能。它支持各种统计方法和假设检验&#xff0c;例如 t-tests、ANOVA、correlation analysis 等。让我们看一些示例代码&…

全网最新最全面的Appium自动化:Appium常用操作之点击滑动类操作

点击&滑动类操作 在进行app自动化的时候,经常会进行点击或滑动的操作,比如点击坐标&#xff0c;左右滑动,上下滑动等&#xff0c;Appium相应提供了解决方案。 坐标的开启步骤&#xff1a; 开发者选项——指针位置开启 坐标展示&#xff1a; 在flick和swipe中都提到了坐标…