Python 内置界面开发框架 Tkinter入门篇 丙(文末有福利彩蛋,今天可是元宵节)
以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「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入门篇 丙(文末有福利彩蛋,今天可是元宵节)的更多相关文章
- Python内置函数详解——总结篇
2个多月来,将3.5版本中的68个内置函数,按顺序逐个进行了自认为详细的解析,现在是时候进行个总结了.为了方便记忆,将这些内置函数进行了如下分类: 数学运算(7个) 类型转换(24个) ...
- Python内置GUI模块Tkinter的几点笔记
组件属性,用法 组件位置 更多
- Python内置函数详解-总结篇
参考链接:http://www.cnblogs.com/sesshoumaru/p/6140987.html
- Python入门之 Python内置函数
Python入门之 Python内置函数 函数就是以功能为导向,一个函数封装一个功能,那么Python将一些常用的功能(比如len)给我们封装成了一个一个的函数,供我们使用,他们不仅效率高(底层都是用 ...
- 浅谈Python内置对象类型——数字篇(附py2和py3的区别之一)
Python是一门面向对象的编程设计语言,程序中每一样东西都可以视为一个对象.Python内置对象可以分为简单类型和容器类型,简单类型主要是数值型数据,而容器类型是可以包含其他对象类型的集体,如序列. ...
- Python基础篇【第2篇】: Python内置函数(一)
Python内置函数 lambda lambda表达式相当于函数体为单个return语句的普通函数的匿名函数.请注意,lambda语法并没有使用return关键字.开发者可以在任何可以使用函数引用的位 ...
- Python之路(第八篇)Python内置函数、zip()、max()、min()
一.python内置函数 abs() 求绝对值 例子 print(abs(-2)) all() 把序列中每一个元素做布尔运算,如果全部都是true,就返回true, 但是如果是空字符串.空列表也返回t ...
- python内置装饰器
前言 接着上一篇笔记,我们来看看内置装饰器property.staticmethod.classmethod 一.property装饰器 1. 普通方式修改属性值 code class Celsius ...
- 几个可以提高工作效率的Python内置小工具
在这篇文章里,我们将会介绍4个Python解释器自身提供的小工具.这些小工具在笔者的日常工作中经常用到,减少了各种时间的浪费,然而,却很容易被大家忽略.每当有新来的同事看到我这么使用时,都忍不住感叹, ...
- 使用Python内置浏览器缓存cookies并做更新
import requests #python内置的微型浏览器,没有界面的 #作用:缓存cookies s = requests.session() print(s.headers) #伪造请求头部, ...
随机推荐
- 如何在bat中进入虚拟环境
很多情况下我们希望在项目中建立一个build.bat用于项目的自动构建,避免每次构建时都需要手动在控制台中输入命令. 例如对于 pyinstall 的项目,只需要如下的实现: pyinstaller ...
- Educational Codeforces Round 130 (Rated for Div. 2) C. awoo's Favorite Problem
https://codeforc.es/contest/1697/problem/C 因为规则中,两种字符串变换都与'b'有关,所以我们根据b的位置来进行考虑: 先去掉所有的'b',如果两字符串不相等 ...
- jmeter接口自动化-通过csv文件读取用例并执行测试
最近在公司测试中经常使用jmeter这个工具进行接口自动化,简单记录下~ 一.在csv文件中编写好用例 首先在csv文件首行填写相关参数(可根据具体情况而定)并编写测试用例.脚本可通过优先级参数控制执 ...
- Go语言核心36讲
你好,我是郝林.今天想跟你聊聊我和Go语言的故事. Go语言是由Google出品的一门通用型计算机编程语言.作为在近年来快速崛起的编程语言,Go已经成功跻身主流编程语言的行列. 它的种种亮点都受到了广 ...
- Java-(array)数组的基本概念 及 Java内存划分
(array)数组的基本概念 数组的概念:是一种容器,可同时存放多个数据值 数组的特点: 1.数组是一种引用数据类型 2.数组当中的多个数据,类型必须统一 3.数组的长度在程序运行期间不可改变 数组的 ...
- UBOOT编译--- UBOOT顶层Makefile中目标_all和all的关系及背景(四)
@ 目录 1. 前言 2. 概述 3. 老版本UBOOT(背景) 4. 新版本UBOOT 5. 参考 1. 前言 UBOOT版本:uboot2018.03,开发板myimx8mmek240. 2. 概 ...
- 【Java SE】Day01 前言、入门程序、常量、变量
回顾一下Java之前学的内容 Day01 前言.入门程序.常量.变量 一.基础知识 莱布尼茨发明二进制,辗转相除与8421位权法互转,1B=1bit=1字节=8位=8byte dos cls清屏dir ...
- mysql基础问题三问(底层逻辑;正在执行;日志观察)
背景:经常面试会遇到且实际工作中也会应用到的三个场景: 目录: 一.mysql查询时的底层原理是什么? 二.如何查看正在执行的mysql语句? 三.如何观察mysql运行过程中的日志信息? - - - ...
- 日爬百万数据的域名限制、url的清洗和管理
一.域名去重1.检测开头:link.startswith('http') txt = "Hello, welcome to my world." x = txt.startswit ...
- selenium常用配置
def init_chrome_options(self,): chrome_options = webdriver.ChromeOptions() # 设置浏览器初始 位置x,y & 宽高x ...