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

本文大概 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 后边
anchor NSEW (or subset) 根据方向定位此控件,NSEW 表示北南东西四个方向
before 控件 widget 将此控件包装在控件 widget 前边
expand bool 类型值 跟着父控件一起伸缩
fill NONE、X、Y、BOTH 选择当控件伸缩时按照哪个方向填充
ipadx amount 在x方向添加内部填充
ipady amount 在y方向添加内部填充
padx amount 在x方向添加填充
pady amount 在y方向添加填充
side TOP、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 列数 放置的控件横跨多少列
ipadx amount 在 x 方向添加内部填充
ipady amount 在 y 方向添加内部填充
padx amount 在 x 方向添加外部填充
pady amount 在 y 方向添加外部填充
row 行序号 指定放置的行,从0开始
rowspan number 放置的控件横跨多少行
sticky NSEW 如果单元格比较大,那么控件的指定边界将贴着单元格。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

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

  1. Python内置函数详解——总结篇

    2个多月来,将3.5版本中的68个内置函数,按顺序逐个进行了自认为详细的解析,现在是时候进行个总结了.为了方便记忆,将这些内置函数进行了如下分类:     数学运算(7个)     类型转换(24个) ...

  2. Python内置GUI模块Tkinter的几点笔记

    组件属性,用法 组件位置 更多

  3. Python内置函数详解-总结篇

    参考链接:http://www.cnblogs.com/sesshoumaru/p/6140987.html

  4. Python入门之 Python内置函数

    Python入门之 Python内置函数 函数就是以功能为导向,一个函数封装一个功能,那么Python将一些常用的功能(比如len)给我们封装成了一个一个的函数,供我们使用,他们不仅效率高(底层都是用 ...

  5. 浅谈Python内置对象类型——数字篇(附py2和py3的区别之一)

    Python是一门面向对象的编程设计语言,程序中每一样东西都可以视为一个对象.Python内置对象可以分为简单类型和容器类型,简单类型主要是数值型数据,而容器类型是可以包含其他对象类型的集体,如序列. ...

  6. Python基础篇【第2篇】: Python内置函数(一)

    Python内置函数 lambda lambda表达式相当于函数体为单个return语句的普通函数的匿名函数.请注意,lambda语法并没有使用return关键字.开发者可以在任何可以使用函数引用的位 ...

  7. Python之路(第八篇)Python内置函数、zip()、max()、min()

    一.python内置函数 abs() 求绝对值 例子 print(abs(-2)) all() 把序列中每一个元素做布尔运算,如果全部都是true,就返回true, 但是如果是空字符串.空列表也返回t ...

  8. python内置装饰器

    前言 接着上一篇笔记,我们来看看内置装饰器property.staticmethod.classmethod 一.property装饰器 1. 普通方式修改属性值 code class Celsius ...

  9. 几个可以提高工作效率的Python内置小工具

    在这篇文章里,我们将会介绍4个Python解释器自身提供的小工具.这些小工具在笔者的日常工作中经常用到,减少了各种时间的浪费,然而,却很容易被大家忽略.每当有新来的同事看到我这么使用时,都忍不住感叹, ...

  10. 使用Python内置浏览器缓存cookies并做更新

    import requests #python内置的微型浏览器,没有界面的 #作用:缓存cookies s = requests.session() print(s.headers) #伪造请求头部, ...

随机推荐

  1. 如何在bat中进入虚拟环境

    很多情况下我们希望在项目中建立一个build.bat用于项目的自动构建,避免每次构建时都需要手动在控制台中输入命令. 例如对于 pyinstall 的项目,只需要如下的实现: pyinstaller ...

  2. Educational Codeforces Round 130 (Rated for Div. 2) C. awoo's Favorite Problem

    https://codeforc.es/contest/1697/problem/C 因为规则中,两种字符串变换都与'b'有关,所以我们根据b的位置来进行考虑: 先去掉所有的'b',如果两字符串不相等 ...

  3. jmeter接口自动化-通过csv文件读取用例并执行测试

    最近在公司测试中经常使用jmeter这个工具进行接口自动化,简单记录下~ 一.在csv文件中编写好用例 首先在csv文件首行填写相关参数(可根据具体情况而定)并编写测试用例.脚本可通过优先级参数控制执 ...

  4. Go语言核心36讲

    你好,我是郝林.今天想跟你聊聊我和Go语言的故事. Go语言是由Google出品的一门通用型计算机编程语言.作为在近年来快速崛起的编程语言,Go已经成功跻身主流编程语言的行列. 它的种种亮点都受到了广 ...

  5. Java-(array)数组的基本概念 及 Java内存划分

    (array)数组的基本概念 数组的概念:是一种容器,可同时存放多个数据值 数组的特点: 1.数组是一种引用数据类型 2.数组当中的多个数据,类型必须统一 3.数组的长度在程序运行期间不可改变 数组的 ...

  6. UBOOT编译--- UBOOT顶层Makefile中目标_all和all的关系及背景(四)

    @ 目录 1. 前言 2. 概述 3. 老版本UBOOT(背景) 4. 新版本UBOOT 5. 参考 1. 前言 UBOOT版本:uboot2018.03,开发板myimx8mmek240. 2. 概 ...

  7. 【Java SE】Day01 前言、入门程序、常量、变量

    回顾一下Java之前学的内容 Day01 前言.入门程序.常量.变量 一.基础知识 莱布尼茨发明二进制,辗转相除与8421位权法互转,1B=1bit=1字节=8位=8byte dos cls清屏dir ...

  8. mysql基础问题三问(底层逻辑;正在执行;日志观察)

    背景:经常面试会遇到且实际工作中也会应用到的三个场景: 目录: 一.mysql查询时的底层原理是什么? 二.如何查看正在执行的mysql语句? 三.如何观察mysql运行过程中的日志信息? - - - ...

  9. 日爬百万数据的域名限制、url的清洗和管理

    一.域名去重1.检测开头:link.startswith('http') txt = "Hello, welcome to my world." x = txt.startswit ...

  10. selenium常用配置

    def init_chrome_options(self,): chrome_options = webdriver.ChromeOptions() # 设置浏览器初始 位置x,y & 宽高x ...