头图

Python 内置界面开发框架 Tkinter入门篇 丙(文末有福利彩蛋,今天可是元宵节)

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」https://mp.weixin.qq.com/s/B1...

本文大概 2874 个字,阅读需花 10 分钟
内容不多,但也花了一些精力
如要交流,欢迎关注我然后评论区留言
谢谢你的点赞收藏分享

进入正文之前先说一件小事,本公众号已改名为【ENG八戒】,原名是【englyf】。改名的理由是什么?以后会告诉朋友们的!

另外文末有福利彩蛋,毕竟今天是元宵节!


这篇文章属于系列文章《Python 内置界面开发框架 Tkinter入门篇》的第三篇,上接《Python 内置界面开发框架 Tkinter入门篇 乙》,欢迎关注我的微信公众号「ENG八戒」查看这个系列相关文章。

界面布局

关于 Tkinter 框架的 GUI 布局,其实官方没有提供对应的图形化工具可用,但是网上有一些开源的小工具可以使用。这里不打算介绍这些小工具的使用,而是直接用框架提供的几何图形管理器来布局,比如上面提到过的 pack() 就是其中一种。这里提到的几何图形管理器也就是其它框架里常说的布局管理器。

Tkinter 框架提供的布局管理器有:pack、grid、place 三种。每一个控件只可以使用一种布局管理器,不同控件使用的布局管理器可以不一样。

pack

形象点说, pack 就是把控件包装在一个矩形区域,这个区域大小足够放置控件,而且默认置中。pack 是最简单的布局管理器,也称之为包装布局。

直接试一试用 pack 来布局三个静态标签 Label,默认设置(pack() 传入参数为空)

import tkinter as tk

window = tk.Tk()
lbl_1 = tk.Label(
    master=window,
    text="label 1",
    fg="black",
    bg="red",
    width=10,
    height=5
    )
lbl_1.pack()
lbl_2 = tk.Label(
    master=window,
    text="label 2",
    fg="black",
    bg="yellow",
    width=10,
    height=5
    )
lbl_2.pack()
lbl_3 = tk.Label(
    master=window,
    text="label 3",
    fg="black",
    bg="blue",
    width=10,
    height=5
    )
lbl_3.pack()
window.mainloop()

看看显示效果

可以看到,默认 pack 会在父窗口 window 中垂直方向按顺序包装排列这三个静态标签 Label。

那么,如果我需要让这几个标签水平排列呢?可以这样子改

lbl_1.pack(side=tk.LEFT)
...
lbl_2.pack(side=tk.LEFT)
...
lbl_3.pack(side=tk.LEFT)

看看显示效果

pack(side=tk.TOP) 和默认设置等价。

简单汇总介绍一下其它的参数

参数赋值说明
after控件 widget将此控件包装在控件 widget 后边
anchorNSEW (or subset)根据方向定位此控件,NSEW 表示北南东西四个方向
before控件 widget将此控件包装在控件 widget 前边
expandbool 类型值跟着父控件一起伸缩
fillNONE、X、Y、BOTH选择当控件伸缩时按照哪个方向填充
ipadxamount在x方向添加内部填充
ipadyamount在y方向添加内部填充
padxamount在x方向添加填充
padyamount在y方向添加填充
sideTOP、BOTTOM、LEFT、RIGHT把控件往哪边添加

很多时候开发界面都需要让里边的控件跟随窗口自动拉伸大小,来看一下上面的代码应该怎么改

lbl_1.pack(fill=tk.BOTH, expand=tk.TRUE)
...
lbl_2.pack(fill=tk.BOTH, expand=tk.TRUE)
...
lbl_3.pack(fill=tk.BOTH, expand=tk.TRUE)

启动的时候,还没有拉伸窗口

然后拉伸看看

grid

如名字表述,grid 会把父窗口划分成行列,然后根据调用时传入参数 row,column 确定把控件放置在对应的行列中。grid 也称之为格子布局。

还是以静态标签为例,创建 3x3 的矩阵标签。为了凸显各个标签的边界,这里还需要添加 Frame 控件,每个标签放置于单独的 Frame 中。

import tkinter as tk

window = tk.Tk()

for i in range(3):
    for j in range(3):
        frame = tk.Frame(
            master=window,
            relief=tk.RAISED,
            borderwidth=1
        )
        frame.grid(row=i, column=j)
        label = tk.Label(
            master=frame,
            text=f"Row {i}\nColumn {j}"
            )
        label.pack()

window.mainloop()

可以看到,上面这个例子布局时,只有 Frame 才需要应用 grid 管理器,因为每个标签和 Frame 一一对应,所以标签不需要重复应用格子布局。

看看显示效果

简单汇总介绍一下其它的参数

参数赋值说明
column列序号指定放置的列,从0开始
columnspan列数放置的控件横跨多少列
ipadxamount在 x 方向添加内部填充
ipadyamount在 y 方向添加内部填充
padxamount在 x 方向添加外部填充
padyamount在 y 方向添加外部填充
row行序号指定放置的行,从0开始
rowspannumber放置的控件横跨多少行
stickyNSEW如果单元格比较大,那么控件的指定边界将贴着单元格。NSEW分别对应顶部、底部、右边、左边边界

细心的朋友会发现,一旦拉伸上面的那个矩阵标签窗口,窗口界面就会露出部分底面,矩阵标签没有跟随一起拉伸。

这样明显和我们的预期不符合,这个问题怎么解决呢?

可以调用父窗口的 columnconfigure() 和 rowconfigure() 方法配置各列和行的伸缩比。这两个方法都有三个输入参数,看下面的表格

参数说明
index序号,指定特定的行或列,可以是单个行列序号值,也可以是代表多个行或列的列表
weight伸缩权重
minsize最小宽度值

现在来看看怎么改,才能让矩阵标签跟随父窗口一起拉伸?

import tkinter as tk

window = tk.Tk()

for i in range(3):
    window.rowconfigure(i, weight=1)
    window.columnconfigure(i, weight=1)

    for j in range(3):
        frame = tk.Frame(
            master=window,
            relief=tk.RAISED,
            borderwidth=1
        )
        frame.grid(row=i, column=j)
        label = tk.Label(
            master=frame,
            text=f"Row {i}\nColumn {j}"
            )
        label.pack()

window.mainloop()

看看拉伸之后的显示效果

perfect!另外需要提一下,grid 具有 pack 能做的所有功能,但是使用的形式更简单,因此应该作为更优先的布局管理器。

place

place 用于对控件精确定位的场合。使用的时候需要传入参数 x 和 y 分别用于指定控件的放置位置坐标值 x 和 y,传入的 x 和 y 是基于父控件的左上角为原点的坐标系,单位是像素点。

大多数界面应用里,控件都不需要精确的定位。但是某些,比如地图应用里,就的确需要对元素的精确定位了。

下面举个栗子,在窗口里不同位置放置各一个标签

import tkinter as tk

window = tk.Tk()

label1 = tk.Label(
    master=window,
    text="place (0, 0)",
    bg="yellow"
    )
label1.place(x=0, y=0)

label2 = tk.Label(
    master=window,
    text="place (40, 40)",
    bg="blue"
    )
label2.place(x=40, y=40)

window.mainloop()

看看上面代码的显示效果

说回来,place 的参数xy单位是像素,那么在不同的系统下,字体类型和大小都是不同的,那么被放置的控件就有可能超出窗口边界。因此 place 真的不常用,关于 place 进一步的信息就不再展开了。

交互

上面介绍的内容都仅限于 Tkinter 界面的可视化设计,那么现在是时候介绍一下Tkinter 界面和用户的互动了。

比如,Tkinter 界面对于事件的响应是怎么发生的?

一般,在 Tkinter 中通过预先绑定事件和响应处理函数,每当事件发生时,主窗口的 mainloop 就会收到事件,然后根据绑定信息,查找到响应处理函数并调用,来达到交互的效果。绑定的通用方法是调用各个控件的 bind()。

比如,下面我们来实现一个简单的键盘响应互动,每次按键按下时就把对应的按键打印出来

import tkinter as tk

def handle_keypress(event):
    print(event.char)

window = tk.Tk()
window.bind("<Key>", handle_keypress)
window.mainloop()

上面的代码没有添加额外的控件,除了有个空白的主窗口。其中,对主窗口 window 绑定了按键事件 Key 和处理函数 handle_keypress。

调用 bind() 最少要求输入两个参数,一个是形式为 "<event_name>" 的事件,另一个是事件处理函数。

定义处理函数 handle_keypress 时,唯一做的事情是把传入的事件字符打印到标准终端。

每当按下键盘的按键,命令行终端就会输出对应的按键。

但是,对于按钮 Button 来说,点击事件的触发处理可以不需要使用 bind(),仅需要在实例化控件 Button 时,传入处理函数给 command 参数即可,初始化过程会自动绑定 click 事件的响应。

上代码看看

import tkinter as tk

def handle_keypress():
    print("clicked")

window = tk.Tk()
button = tk.Button(
    master=window,
    text="click me!",
    command=handle_keypress
    )
button.pack()
window.mainloop()

运行程序

用鼠标点击一下界面上的按钮,发现终端会输出字符串 clicked


由于篇幅受限,本系列教程还未完结,下一篇《Python 内置界面开发框架 Tkinter入门篇 丁》将在本公众号稍后推送,如果你对此教程有兴趣或者想和我一起交流更多精彩内容,欢迎关注我的微信公众号 【ENG八戒】,等着你哦!

《元宵彩蛋》

闹元宵了,《八戒陪你一起闹元宵2023

1 声望
0 粉丝
0 条评论
推荐阅读
Python:Excel自动化实践入门篇 甲【送图书门票】
*以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「englyf」[链接]***正文开始之前,先给朋友们宣布个好消息,文末有送图书和门票的福利活动,不要错过哦!今天周五,马上就到下午6点钟,该下...

八戒englyf阅读 128

封面图
数据结构与算法:二分查找
一、常见数据结构简单数据结构(必须理解和掌握)有序数据结构:栈、队列、链表。有序数据结构省空间(储存空间小)无序数据结构:集合、字典、散列表,无序数据结构省时间(读取时间快)复杂数据结构树、 堆图二...

白鲸鱼9阅读 5.2k

滚蛋吧,正则表达式!
你是不是也有这样的操作,比如你需要使用「电子邮箱正则表达式」,首先想到的就是直接百度上搜索一个,然后采用 CV 大法神奇地接入到你的代码中?

良许3阅读 1.4k

搭个ChatGPT算法模型,从哪开始?
最近 ChatGPT 很火,火到了各行各业。记得去年更多的还是码农最新体验后拿它搜代码,现在各行各业都进来体验,问它咋理财、怎么写报告和给小孩起名。😂 也因此让小傅哥在头条的一篇关于 ChatGPT 的文章都有了26万...

小傅哥6阅读 1.1k

封面图
程序员适合创业吗?
大家好,我是良许。从去年 12 月开始,我已经在视频号、抖音等主流视频平台上连续更新视频到现在,并得到了不错的评价。每个视频都花了很多时间精力用心制作,欢迎大家关注哦~考虑到有些小伙伴没有看过我的视频,...

良许3阅读 1.2k

Ubuntu20.04 从源代码编译安装 python3.10
Ubuntu 22.04 Release DateUbuntu 22.04 Jammy Jellyfish is scheduled for release on April 21, 2022If you’re ready to use Ubuntu 22.04 Jammy Jellyfish, you can either upgrade your current Ubuntu syste...

ponponon1阅读 4.5k评论 1

Python实现Windows弹出微信消息通知(可显示发送人和消息内容)
Mac微信是有一个消息通知的,这一点就挺好的,有时候根本不用点开开看就能看到消息内容。而Windows电脑版是没有这个消息通知的,只有右下角图标闪烁。

TANKING3阅读 3.7k评论 1

封面图
1 声望
0 粉丝
宣传栏