Python tkinter 学习笔记(1)-- 第一个窗口之HelloWorld 教程
Python tkinter 学习笔记(2)-- 控件、组件(一)
Tkinter 界面布局(grid\pack\place)
目录
从本章节开始就进入Tkinter 详细学习内容,在对这些复杂问题的讨论和讲解过程中,我这里尽量使用较为简单和通俗的语言进行描述,当然,在理解和概念性上每个人都会有所差异,如果在学习过程中有任何疑问可以留言或者进群:654927708进行讨论。
Tkinter布局方式有三种,一种是网格型布局方式--grid,第二种是相对位置布局方式pack,第三种就是坐标布局下面就具体分别进行讲解。
首先我们来了解一下Tkinter 内部各种控件的继承关系,如下图所示:
由此图可以看出来,所有的wiget里面的控件都继承四个树形,在Widget的下方就是tkinter所有的控件,在上一章节我们已经具体进行了实例讲解。上方就是所有控件继承的样式,其中BaseWidget是基础属性,基本上不需要用户干预,剩余的grid、pack、place就是我们要用到的布局样式。
一、grid 网格型布局
gird网格布局形式可以理解为在一个二位表格里面进行布局,设计过程就像是在制作表格,有点类似于制作Excel或者HTML 的Table表格,其主要属性如下:
option | 解释 |
column | 插件布放的列数值,从0开始。默认值为0 |
columnspan | 正常情况下,一个插件只占一个里无。但是,你可以通过设置。。/077/勺矛来合并一行中的多个邻近单元,并用此单元 放置本插件。比如,w. gr id (row=0, colujTin= 2, columnspan=3),这会把插件kV布置在将第0行的2 , 3,4^]合并后的单兀 中。 |
in_ | 用in_=w2可以将%登记为的child插件。屹必须是w创建时指定parent插件的child插件。 |
ipadx | X方向的内部填充。在插件内部,左右方向各填充指定长度的空间。 |
ipady | y方向的内部填充。在插件内部,上下方向各填充指定长度的空间。 |
padx | X方向的外部填充。在插件外部,左右方向各填充指定长度的空间。 |
pady | y方向的内部填充。在插件内部,上下方向各填充指定长度的空间。 |
row | 插件布放的行数值,从0开始。默认值为末布放行的下一个数值。 |
rowspan | 正常情况下,一个插件只占一个但愿。但是,你可以通过设置rowspan来合并一列中的多个邻近单元,并用此单元放 置本插件。比如,w. grid(row=3, colujTin= 2, rowsparF4, columnspan=3),这会把插件IV布置在合并了20个空元的区域中, 也就是3-6行和2-6列。 |
sticky | 这个参数用来确定:在插件正常尺寸下,如何分配空无中多余的空间。具体如下。 |
备注:
•如果没有声明sticky属性,默认将插件居中于稣中。 |
•通过设置sticky=tk. NE (靠右上方),sticky=tk. SE (W右下方),sticky=tk. SW (W左下方),sticky=tk. W (W左上方),可以将插件布置在空元的某个免落。 |
•通过设置sticky=tk. N靠上方),sticky=tk.E (靠右方),sticky=tk. S (靠下方),sticky=tk.W (靠左方),可以将插件布置在空元的某个方向上。 |
•通过设置sticky=tk. N+tk. S ,在垂直方向上延伸插件,并保持水平居中。 |
•通过设置sticky=tk.E+tk.W ,在水平方向上延伸插件,并保持垂直居中。 |
•通过设置sticky=tk. N+tk. E+tk. W ,在水平和垂直方向上延伸插件,填满单元。 |
•也可以使用其他的组合。比如,sticky=tk.N+tk.S+tk.W ,在垂直方向上延伸插件,并靠左布放。 |
这里我们以最常用的登录界面作为一个讲解,先用表格画一下简单的界面设计图,如下所示:
Label1 | Entry1 | Image1 |
Label2 | Entry2 | |
button1 | button2 |
从这个图里面我们可以看到,这是一个3x3的表格,左边两列按部就班,最右边那一列就要合并三行,所以,代码就应该如下:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 引用tkinter窗口
import tkinter as tk
# 创建窗口
win = tk.Tk()
# 给创建的窗口添加一个标题
win.title('第一个窗口')
# 设置窗口大小,和屏幕的高度,即('窗口宽度x窗口高度+屏幕顶边距离+屏幕左边距离')
win.geometry('320x150+200+200')
# grid 的column-> 列,row-> 行,rowspan-> 合并行
# 第一列
tk.Label(text="UserName:").grid(column=0, row=0) # 第一行 第一列
tk.Entry(width=15).grid(column=1, row=0) # 第二行 第一列
tk.Button(text="登录").grid(column=0, row=2) # 第三行 第一列
# 第二列
tk.Label(text="PassWord:").grid(column=0, row=1) # 第二行 第2列
tk.Entry(width=15).grid(column=1, row=1) # 第二行 第二列
tk.Button(text="注册").grid(column=1, row=2) # 第三行 第二列
# 加载图片
pic = tk.PhotoImage(file="2.png")
# 第三列,从第一行开始合并三行
tk.Label(image=pic).grid(column=2, row=0, rowspan=2)
# 主窗口循环
win.mainloop()
效果:
解析:这种布局较为好理解,就是网格化布局,需要提前对要设计的界面进行规划。
二、pack 布局方式
pack相对于grid和place的布局方式就比较粗犷,在对页面整体布局中设计只要求大致的方位,然后在固定的方位放置对应的Frame、控件等内容即可,这里需要注意的就是grid和pack不要放在同一个窗口界面中使用,其主要属性有:
option | 解释 |
anchor | 1. 控制组件在 pack 分配的空间中的位置 |
2. "n", "ne", "e", "se", "s", "sw", "w", "nw", 或者 "center" 来定位(ewsn 代表东西南北,上北下南左西右东) | |
3. 默认值是 "center" | |
expand | 1. 指定是否填充父组件的额外空间 |
2. 默认值是 False | |
fill | 1. 指定填充 pack 分配的空间 |
2. 默认值是 NONE,表示保持子组件的原始尺寸 | |
3. 还可以使用的值有:"x"(水平填充),"y"(垂直填充)和 "both"(水平和垂直填充) | |
in_ | 1. 将该组件放到该选项指定的组件中 |
2. 指定的组件必须是该组件的父组件 | |
ipadx | 指定水平方向上的内边距 |
ipady | 指定垂直方向上的内边距 |
padx | 指定水平方向上的外边距 |
pady | 指定垂直方向上的外边距 |
side | 1. 指定组件的放置位置 |
2. 默认值是 "top" | |
3. 还可以设置的值有:"left","bottom","right" |
要使用pack布局需要理解两个概念,就是独占、共享、扩展空间大小,比如设置了一个控件属性.pack(side="top"),那么上部区域就是这个控件的独享控件,剩下的区域就是共享控件,如下图所示:
其中黄色区域就是控件原有大小,剩下红色的区域就是共享的控件,即通过expand设置是否占用共享空间;剩下蓝色区域就是可扩展控件,可以通过fill进行设置是否占空扩展空间,pack的side属性,除了默认的top,left,bottom,right之外,在默认之初给side分配了九个区域,分别通过NW、N、NE、W 、Center、E、SW、S、SE进行锚定,两种属性的使用方法是一致的,主要就是看expand、fill是否开启进行空间的占用,如下图所示:
这里以聊天界面作为一个实例进行讲解,先画一下布局图,如下图所示:
实现代码如下:
# pack()方法使用
import tkinter as tk
# 主窗口
win = tk.Tk()
win.geometry("900x800+400+200")
win.title("与 [xxx] 的聊天界面")
# 第一个框架,居左,y方向全部填充
frame1 = tk.Frame(win)
frame1.pack(side="left", fill="y", expand=0)
# 创建各种按钮,所有的按钮归属第一个框架
btn1 = tk.Button(frame1, text="群聊")
btn1.pack(side="top")
btn2 = tk.Button(frame1, text="好友")
btn2.pack(side="top")
btn3 = tk.Button(frame1, text="收藏")
btn3.pack(side="top")
btn4 = tk.Button(frame1, text="邮箱")
btn4.pack(side="top")
# 创建中间框架,消息内容展示框属于第二个框架,顶部
frame2 = tk.Frame(win)
frame2.pack(side="left", fill="y", expand=0, ipadx=150)
MsgText = tk.Text(frame2, width=35, height=45)
MsgText.pack(side="top", fill="x")
# 中间框架嵌套第一个框架,位于MsgText下方,x方向扩展,所有的按钮属于frame2_n1框架
frame2_n1 = tk.Frame(frame2)
frame2_n1.pack(side="top", fill="x")
btn1 = tk.Button(frame2_n1, text="表情")
btn1.pack(side="left")
btn2 = tk.Button(frame2_n1, text="截屏")
btn2.pack(side="left")
btn3 = tk.Button(frame2_n1, text="发送文件")
btn3.pack(side="left")
# 中间框架嵌套第二个框架,位于frame2_n1下方,SendText属于frame2_n2框架
frame2_n2 = tk.Frame(frame2)
frame2_n2.pack(side="top", fill="x")
SendText = tk.Text(frame2_n2, width=35, height=10)
SendText.pack(side="top", fill="x")
# 中间框架嵌套第三个框架,位于frame2_n2下方,发送按钮(btn4)属于frame2_n3框架
frame2_n3 = tk.Frame(frame2)
frame2_n3.pack(side="top", fill="x")
btn4 = tk.Button(frame2_n3, text="发送(Send)")
btn4.pack(side="right")
# 创建右边框架,y方向填充
frame3 = tk.Frame(win)
frame3.pack(side="right", expand=0, fill="y", ipadx=300)
pic = tk.PhotoImage(file="3.png")
bnr = tk.Label(frame3, image=pic)
bnr.pack(side="top")
# 开始窗口的事件循环
win.mainloop()
效果图:
pack这种布局方式有点类似HTML CSS,在使用过程中可以使用Frame模块进行嵌套,已完成复杂的界面设计。