Python 图形界面框架TkInter之在源码中找pack方法

当我们在学习 Python 编程语言时,经常会用到 Python 的图形界面框架 Tkinter。而 Tkinter 的布局管理器 Layout Manager 有三种,分别是 pack、grid、place。

本篇攻略主要介绍如何在 Tkinter 源码中找到 pack 方法。在 Tkinter 的源码中,pack 方法主要由两个类完成,分别是:CorePackPack. 这两个类分别定义了 pack 的基础和具体实现。

首先,我们可以在 Python 安装目录下找到 Tkinter 源码的位置。我们以 Python 3.9.2 版本为例,可以在以下路径找到 tkinter 的源码:

C:\Users\UserName\AppData\Local\Programs\Python\Python399\Lib\tkinter

其中,appdatausername 可以根据你的电脑用户名和操作系统版本而变化。接着,我们打开 tkinter 目录下的 __init__.py 文件,可以看到以下代码:

from tkinter import *
import tkinter.ttk as ttk
import tkinter.font as font

# 模块注释...

__init__.py 中,我们已经直接导入了 tkinter 模块的全部内容。而 tkinter 模块中的 pack 布局管理器,就是通过 CorePackPack 两个类完成的。下面,我们详细介绍一下这两个类的作用:

CorePack

CorePack 类是 Pack 类的父类,它定义了 pack 的一些基本属性和方法。它的主要作用如下:

  1. 定义了一些默认的参数,例如:fill="none", expand="no"
  2. 声明一些实例变量,例如:self._args, self._options
  3. 定义了一些实例方法,例如:_setitem, _option_dict, _option_db, _options.

下面是 CorePack 类的完整代码示例:

class CorePack:
    # 默认参数
    _default = {
        "anchor": "center",
        "expand": "no",
        "fill": "none",
        "ipadx": 0,
        "ipady": 0,
        "padx": 0,
        "pady": 0,
        "side": "top"
    }

    def _setitem(self, args, kwargs):
        """处理参数"""
        if len(args) == 1:
            # 传递 option 字典
            options = args[0]
        else:
            # 将 args 转化为 list,方便后面操作
            options = list(args)

        # 合并 options 和 kwargs 中的参数
        for key, value in kwargs.items():
            options.append(f"-{key}")
            options.append(value)

        return options

    def _option_dict(self, kwargs):
        """将参数映射成字典"""
        options_dict = {}

        for key in kwargs:
            if key == "side" and kwargs[key]:
                options_dict[key] = kwargs[key][0]
            else:
                options_dict[key] = kwargs[key]

        return options_dict

    def _option_db(self, kwargs):
        """将参数映射成字典"""
        options_dict = {}

        for key in kwargs:
            if isinstance(kwargs[key], tuple):
                options_dict[key] = ",".join(map(str, kwargs[key]))
            else:
                options_dict[key] = kwargs[key]

        return options_dict

    def _options(self, args, kwargs):
        """获取选项参数"""
        if len(args) == 1 and isinstance(args[0], (int, float, str)):
            # 将 args 转化为 list,方便后面操作
            args = list(args)
            options = []

            # args 中的第一个参数为 side
            kwargs["side"] = args.pop(0)

            options += self._setitem(args, kwargs)
        else:
            options = self._setitem(args, kwargs)

            if "side" not in kwargs:
                options.insert(0, "-top")

            if not any(x for x in options if x.startswith("-side=")):
                options.insert(0, "-side=top")

        return self._option_dict(self._option_db(options))

Pack

Pack 类是 CorePack 类的子类,它是 pack 的具体实现。Pack 类的主要作用如下:

  1. 声明一些实例变量,例如:self.masterself.slaves
  2. 定义了一些实例方法,例如:forget, info, place, propagate, slaves, unpack

下面是 Pack 类的完整代码示例:

class Pack(CorePack):
    """pack 布局管理器"""

    def __init__(self, master=None, cnf={}, **kw):
        super().__init__()

        # 父容器
        self.master = master

        # 子容器
        self.slaves = []

        # 保存配置信息
        self._configure(cnf, kw)

    def pack_configure(self, cnf={}, **kw):
        """设置控件属性"""
        self._configure(cnf, kw)

    def pack_forget(self):
        """隐藏控件"""
        for slave in self.slaves:
            slave.pack_forget()

    def pack_info(self, name=None):
        """返回控件的属性"""
        if name:
            info_list = []

            for slave in self.slaves:
                info = slave.pack_info()

                if info["name"] == name:
                    return info

            raise TclError(f"no {name} packed in {self}")

        elif len(self.slaves) == 1:
            return self.slaves[0].pack_info()

        else:
            info_list = []

            for slave in self.slaves:
                name = slave.pack_info()["name"]

                if name:
                    info_list.append(name)

            return tuple(info_list)

    def pack_propagate(self, flag=None):
        """允许或禁止控件自动调整"""
        if flag is None:
            flag = 1

        elif isinstance(flag, str):
            flag = {"yes": 1, "no": 0, "1": 1, "0": 0}[flag]

        elif flag:
            flag = 1

        else:
            flag = 0

        self.master.pack_propagate(flag)

    def pack_slaves(self):
        """返回子控件"""
        return self.slaves

    def pack_unpack(self):
        """取消控件"""
        for slave in self.slaves:
            slave.pack_unpack()

    def pack_configure(self, cnf=None, **kw):
        """设置控件属性"""
        if cnf is None:
            cnf = {}

        self._configure(cnf, kw)

    def _configure(self, cnf={}, kw={}):
        """设置控件属性"""
        cnf = self._option_db(cnf)
        kw = self._option_db(kw)

        self.master.tk.call(
            ("pack", "configure", self._name) +
            self._options(self._args, cnf, kw))

    def _options(self, args, cnf, kw):
        """获取选项参数"""
        options = super()._options(args, kw)

        if cnf or args:
            options += ("-",)

        return options + super()._options(args, cnf)

上述代码中,我们可以看到 Pack 类中的 pack_configurepack_forgetpack_infopack_propagatepack_slavespack_unpack 这几个方法,这些方法就是 pack 的具体实现。

同时,Pack 类中还包含 _configure_options 这两个私有方法,它们分别用于配置控件的属性和获取选项参数。需要注意的是,_configure_options 方法定义在 CorePack 类中,因此 Pack 类中只需要继承即可。

通过上述代码和解释,我们已经知道如何在 Tkinter 源码中找到 pack 方法,并且了解了 CorePackPack 两个类的作用。接下来,我们举两个例子,更具体地说明如何使用 pack 的方法。

例子 1:使用 pack 布局管理器进行水平排列

import tkinter as tk

root = tk.Tk()

for i in range(3):
    tk.Button(root, text=f"Button {i}").pack(side="left")

root.mainloop()

这个例子中,我们使用了 packside 参数实现水平排列。在 for 循环中创建三个按钮,并将它们都设置为 side="left",即使它们水平排列。

例子 2:使用 pack 布局管理器进行竖直排列

import tkinter as tk

root = tk.Tk()

for i in range(3):
    tk.Button(root, text=f"Button {i}").pack(side="top")

root.mainloop()

这个例子中,我们同样使用了 packside 参数实现竖直排列。在 for 循环中创建三个按钮,并将它们都设置为 side="top",即使它们竖直排列。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python 图形界面框架TkInter之在源码中找pack方法 - Python技术站

(0)
上一篇 2023年6月13日
下一篇 2023年6月13日

相关文章

  • Python多进程模式实现多核CPU并行计算

    下面是详细的讲解: Python多进程模式实现多核CPU并行计算 什么是多进程模式? 在计算机中,多进程是指一个程序同时运行多个进程。每个进程都有自己的地址空间、内存使用、文件句柄以及系统资源,进程之间可以相互通信或者互相影响。多进程可以利用多核CPU并行计算,提高程序的运行效率。 Python多进程模式实现 Python标准库中提供了multiproces…

    python 2023年6月6日
    00
  • Python基本类型的连接组合和互相转换方式(13种)

    Python基本类型有13种,它们分别是:整数(int)、长整数(long)、浮点数(float)、复数(complex)、字符串(str)、列表(list)、元组(tuple)、集合(set)、字典(dict)、布尔型(bool)、空类型(NoneType)、字节类型(bytes)、字节数组类型(bytearray)。这些基本类型之间可以互相转换,并且可以…

    python 2023年5月14日
    00
  • 适用于 Python 的 MS 分析服务 OLAP API [关闭]

    【问题标题】:MS Analysis Services OLAP API for Python [closed]适用于 Python 的 MS 分析服务 OLAP API [关闭] 【发布时间】:2023-04-06 22:34:01 【问题描述】: 我正在寻找一种方法来连接到 MS Analysis Services OLAP 多维数据集、运行 MDX 查…

    Python开发 2023年4月7日
    00
  • python中的load、loads实现反序列化示列

    下面是 Python 中的 load 和 loads 函数的反序列化示例: loads loads 函数用于将 JSON 格式的字符串反序列化为 Python 对象。示例如下: import json # JSON 格式的字符串 json_str = ‘{"name": "Jack", "age":…

    python 2023年6月3日
    00
  • python将列表添加到列表错误[重复]

    【问题标题】:python add list into a list error [duplicate]python将列表添加到列表错误[重复] 【发布时间】:2023-04-04 02:48:01 【问题描述】: 编写python代码将列表添加到列表中,如下: mbk = MiniBatchKMeans(n_clusters=cluster_number)…

    Python开发 2023年4月6日
    00
  • 海王小姐姐悄悄问我怎么在PC端登录多个微信

    以下是详细的攻略: 方法一:使用微信Web网页版 首先打开微信的官方网站:https://wx.qq.com/,在打开的页面中选择“在其他设备上登录”,微信会弹出二维码,需要用手机扫描二维码进行确认登录。 确认登录后,在电脑浏览器中就可以使用微信Web网页版,可以与手机端同步聊天记录以及进行聊天。 该方法支持在多个浏览器窗口登录,因此可以在PC端同时登录多个…

    python 2023年6月5日
    00
  • 解决AttributeError:’NoneTypeobject’ has no attribute’Window’的问题(亲测有效)

    解决 AttributeError: ‘NoneType’ object has no attribute ‘Window’ 的问题可以按照以下攻略进行: 问题分析 这个错误通常出现在使用 PyQt5 编写 GUI 程序时,如果在程序中调用了一个未经初始化的窗口对象,就会报出类似以下的错误信息: AttributeError: ‘NoneType’ obje…

    python 2023年6月6日
    00
  • 三行Python代码提高数据处理脚本速度

    好的。首先,可以使用Python内置的timeit模块来测试代码的执行速度,以便比较不同算法或优化方法的效果。一般来说,提高代码性能的方法可以大致分为以下三类: 使用更高效的算法或数据结构; 使用更好的编程技巧和语法; 使用更快的底层库或模块。 下面,我们来详细讲解如何使用三行Python代码提高数据处理脚本速度: 使用更高效的算法或数据结构 在Python…

    python 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部