写点什么

Python 内置界面开发框架 Tkinter 入门篇 丙

作者:eng八戒
  • 2023-02-16
    广东
  • 本文字数:3169 字

    阅读完需:约 10 分钟

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) 和默认设置等价。


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



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


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 一一对应,所以标签不需要重复应用格子布局。


看看显示效果



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



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



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


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



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


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

用户头像

eng八戒

关注

我的微信公众号 englyf 2018-06-01 加入

一枚工程师Engineer自称八戒。从事过嵌入式、GUI、系统集成,涉猎C/C++、Qt、Python、IOT、机器人各领域,不设上限。作为技术传播的年度优秀作者,喜爱读书和写作之余,也爱分享生活乐趣。

评论

发布
暂无评论
Python 内置界面开发框架 Tkinter入门篇 丙_Python_eng八戒_InfoQ写作社区