当前位置:   article > 正文

python3基础知识复习 --TKinter GUI的终极选择(2)_tkinter state

tkinter state

事件绑定

一个 Tkinter 应用程序大部分时间花费在事件循环中(通过 mainloop() 方法进入)。事件可以有各种来源:包括用户触发的鼠标和键盘操作和窗口管理器触发的重绘事件(在多数情况下是由用户间接引起的)。Tkinter 提供一个强大的机制可以让你自由地处理事件,对于每个组件来说,你可以通过 bind() 方法将函数或方法绑定到具体的事件上

widget.bind(event, handler)

当被触发的事件满足该组件绑定的事件时,Tkinter 就会带着事件对象(Event)去调用 handler() 方法。

eg: 我们使用 Frame 组件的 bind() 方法将鼠标点击事件(<Button-1>)和我们自定义的 callback() 方法绑定起来。那么运行后的结果是——当你在点击鼠标左键的时候,IDLE 会相应的将鼠标的位置显示出来(event.x, event.y)

只有当组件获得焦点的时候才能接收键盘事件(Key),下边例子中我们用 focus_set() 获得焦点,当你你可以设置 Frame 的 takefocus 选项为 True,然后使用 Tab 将焦点转移上来。(敲击位置 repr(event.char))

下方主要内容:

  • *事件序列
  • *type
  • *modifier
  • *Event 对象
  • *Key names

事件序列

Tkinter 使用一种称为事件序列的机制来允许用户定义事件,用户需使用 bind() 方法将具体的事件序列与自定义的方法相绑定。

<modifier-type-detail>

  • 事件序列是包含在尖括号(<…>)中
  • type 部分的内容是最重要的,它通常用于描述普通的事件类型,例如鼠标点击或键盘按键点击(详见下方)。
  • modifier 部分的内容是可选的,它通常用于描述组合键,例如 Ctrl + c,Shift + 鼠标左键点击(详见下方)。
  • detail 部分的内容是可选的,它通常用于描述具体的按键,例如 Button-1 表示鼠标左键。
    EG:
事件序列含义
<Button-1>用户点击鼠标左键
<KeyPress-H>用户点击 H 按键
<Control-Shift-KeyPress-H>用户同时点击 Ctrl + Shift + H

type

type含义
Activate当组件的状态从“未激活”变为“激活”的时候触发该事件
Button

1. 当用户点击鼠标按键的时候触发该事件

2. detail 部分指定具体哪个按键:<Button-1>鼠标左键,<Button-2>鼠标中键,<Button-3>鼠标右键,<Button-4>滚轮上滚(Linux),<Button-5>滚轮下滚(Linux)

ButtonRelease

1. 当用户释放鼠标按键的时候触发该事

2. 在大多数情况下,比 Button 要更好用,因为如果当用户不小心按下鼠标,用户可以将鼠标移出组件再释放鼠标,从而避免不小心触发事件

Configure当组件的尺寸发生改变的时候触发该事件
Deactivate当组件的状态从“激活”变为“未激活”的时候触发该事件
Destroy当组件被销毁的时候触发该事件
Enter

1. 当鼠标指针进入组件的时候触发该事件

2. 注意:不是指用户按下回车键

Expose当窗口或组件的某部分不再被覆盖的时候触发该事件
FocusIn

1. 当组件获得焦点的时候触发该事件

2. 用户可以用 Tab 键将焦点转移到该组件上(需要该组件的 takefocus 选项为 True)

3. 你也可以调用 focus_set() 方法使该组件获得焦点(见上方例子)

FocusOut当组件失去焦点的时候触发该事件
KeyPress

1. 当用户按下键盘按键的时候触发该事件

2. detail 可以指定具体的按键,例如 <KeyPress-H>表示当大写字母 H 被按下的时候触发该事件

3. KeyPress 可以简写为 Key

KeyRelease当用户释放键盘按键的时候触发该事件
Leave当鼠标指针离开组件的时候触发该事件
Map

1. 当组件被映射的时候触发该事件

2. 意思是在应用程序中显示该组件的时候,例如调用 grid() 方法

Motion当鼠标在组件内移动的整个过程均触发该事件
MouseWheel

1. 当鼠标滚轮滚动的时候触发该事件

2. 目前该事件仅支持 Windows 和 Mac 系统,Linux 系统请参考 Button

Unmap

1. 当组件被取消映射的时候触发该事件

2. 意思是在应用程序中不再显示该组件的时候,例如调用 grid_remove() 方法

Visibility当应用程序至少有一部分在屏幕中是可见的时候触发该事件

modifier

在事件序列中,modifier 部分的内容可以是以下这些:

modifier含义
Alt当按下 Alt 按键的时候
Any

1. 表示任何类型的按键被按下的时候

2. 例如 <Any-KeyPress> 表示当用户按下任何按键时触发事件

Control当按下 Ctrl 按键的时候
Double

1. 当后续两个事件被连续触发的时候

2. 例如 <Double-Button-1> 表示当用户双击鼠标左键时触发事件

Lock当打开大写字母锁定键(CapsLock)的时候
Shift当按下 Shift 按键的时候
Triple跟 Double 类似,当后续三个事件被连续触发的时候

Event 对象

当 Tkinter 去回调你定义的函数的时候,都会带着 Event 对象(作为参数)去调用,Event 对象以下这些属性你可以使用:

属性含义
widget产生该事件的组件
x, y当前的鼠标位置坐标(相对于窗口左上角,像素为单位)
x_root, y_root当前的鼠标位置坐标(相对于屏幕左上角,像素为单位)
char按键对应的字符(键盘事件专属)
keysym按键名,见下方 Key names(键盘事件专属)
keycode按键码,见下方 Key names(键盘事件专属)
num按钮数字(鼠标事件专属)
width, height组件的新尺寸(Configure 事件专属)
type该事件类型

Key names

当事件为 <Key>,<KeyPress>,<KeyRelease> 的时候,detail 可以通过设定具体的按键名(keysym)来筛选。例如 <Key-H> 表示按下键盘上的大写字母 H 时候触发事件,<Key-Tab> 表示按下键盘上的 Tab 按键的时候触发事件。

下表列举了键盘所有特殊按键的 keysym 和 keycode:

(下边按键码是对应美国标准 101 键盘的“Latin-1”字符集,键盘标准不同对应的按键码不同,但按键名是一样的)

按键名(keysym)按键码(keycode)代表的按键
Alt_L64左边的 Alt 按键
Alt_R113右边的 Alt 按键
BackSpace22Backspace(退格)按键
Cancel110break 按键
Caps_Lock66CapsLock(大写字母锁定)按键
Control_L37左边的 Ctrl 按键
Control_R109右边的 Ctrl 按键
Delete107Delete 按键
Down104↓ 按键
End103End 按键
Escape9Esc 按键
Execute111SysReq 按键
F167F1 按键
F268F2 按键
F369F3 按键
F470F4 按键
F571F5 按键
F672F6 按键
F773F7 按键
F874F8 按键
F975F9 按键
F1076F10 按键
F1177F11 按键
F1296F12 按键
Home97Home 按键
Insert106Insert 按键
Left100← 按键
Linefeed54Linefeed(Ctrl + J)
KP_090小键盘数字 0
KP_187小键盘数字 1
KP_288小键盘数字 2
KP_389小键盘数字 3
KP_483小键盘数字 4
KP_584小键盘数字 5
KP_685小键盘数字 6
KP_779小键盘数字 7
KP_880小键盘数字 8
KP_981小键盘数字 9
KP_Add86小键盘的 + 按键
KP_Begin84小键盘的中间按键(5)
KP_Decimal91小键盘的点按键(.)
KP_Delete91小键盘的删除键
KP_Divide112小键盘的 / 按键
KP_Down88小键盘的 ↓ 按键
KP_End87小键盘的 End 按键
KP_Enter108小键盘的 Enter 按键
KP_Home79小键盘的 Home 按键
KP_Insert90小键盘的 Insert 按键
KP_Left83小键盘的 ← 按键
KP_Multiply63小键盘的 按键
KP_Next89小键盘的 PageDown 按键
KP_Prior81小键盘的 PageUp 按键
KP_Right85小键盘的 → 按键
KP_Subtract82小键盘的 - 按键
KP_Up80小键盘的 ↑ 按键
Next105PageDown 按键
Num_Lock77NumLock(数字锁定)按键
Pause110Pause(暂停)按键
Print111PrintScrn(打印屏幕)按键
Prior99PageUp 按键
Return36Enter(回车)按键
Right102→ 按键
Scroll_Lock78ScrollLock 按键
Shift_L50左边的 Shift 按键
Shift_R62右边的 Shift 按键
Tab23Tab(制表)按键
Up98↑ 按键

Message

Label组件变体用于显示多行文本并能自动换行调整文本尺寸使之适应给定尺寸

通常用于显示简单的文本消息,可以用label代替,显示复杂文本建议用text组件。

参数和方法和label差不多。

root = Tk()

w1 = Message(root, text=“This is a pretty long message, you need wrap it”, width=100)

w1.pack()

Spinbox

Entry组件变体,用于从固定值中选择一个,通常用于在限定数字中选取的情况下代替普通的 Entry 组件。

Spinbox 组件跟 Entry 组件用法非常相似,主要区别是使用 Spinbox 组件,你可以通过范围或者元组指定允许用户输入的内容。

increment

1. 该选项指定当用户每次点击调节箭头的时候递增(递减)的精度

2. 例如 from_=1, to=10, increment=0.5,那么每次用户点击调节箭头的时候,输入框中的数字递增(递减)0.5

validate

validatecommand

1. 该选项设置是否启用内容验证

2. 详见Entry 组件 [bbs.fishc.com]最下方小甲鱼关于验证详解

values

1. 提供两个方法限定用户输入的内容,一种是通过 from_ 和 to 选项设置范围,另一种则是将可选值以元组的形式赋值给 values 选项

2. 例如 values= ("小甲鱼", "~风介~", "wei_Y", "戴宇轩") 则允许用户在这 4 个字符串中选择

wrap

1. 默认情况下(False),当输入框中的值是第一个(最后一个)的时候,再点击向上(向下)调节箭头,内容不会改变

2. 当该选项的值设置为 True,内容开启循环。

PanedWindow

和Frame组件类似的空间管理组件, 但是可以自定义布局允许让用户调整应用程序的空间划分。该组件会为每一个子组件生成一个独立地窗格,用户可以自由调整窗格的大小。

不需要创建root窗口,采用add()方法将其他组件放进去

m = PanedWindow(orient=VERTICAL)

m.pack(fill=BOTH, expand=1)

sashrelief

1. 设置分割线的样式

2. 默认值是:FLAT

3. 另外你还可以设置 SUNKEN,RAISED,GROOVE 或 RIDGE

sashwidth设置分割线的宽度
showhandle

1. 设置是否显示调节窗格的手柄

2. 默认值为 False

在这里插入图片描述

Toplevel

类似root窗口,属于顶级窗口拥有标题,边框等组件,通常用在显示额外的窗口、对话框和其他弹出窗口上。

EG:

	from tkinter import *
	 
	root = Tk()
	 
	# Message组件
	m = Message(root, text='This is a very important message, so sit down and listen to me!', width=100)
	m.pack()
	 
	# Spinbox组件
	Spinbox(root, from_=0, to=10, wrap=True, increment=2).pack(side='left') # 允许内容循环
	Spinbox(root, from_=0, to=10, values=('East', 'West', 'South', 'North')).pack(side='right')
	 
	# PanedWindow组件
	p1 = PanedWindow(showhandle=True, sashrelief=SUNKEN) # 显示句柄和轮廓线
	p1.pack(fill=BOTH, expand=1)
	left = Label(p1, text='left side')
	p1.add(left)
	 
	p2 = PanedWindow(orient=VERTICAL, showhandle=True, sashrelief=SUNKEN)
	p1.add(p2)
	 
	top = Label(p2, text='TOP RIGHT')
	bottom = Label(p2, text='BOTTOM RIGHT')
	p2.add(top)
	p2.add(bottom)
	 
	# Toplevel组件
	def create_tl():
	    tl = Toplevel()
	    tl.attributes('-alpha', 0.5) # 设置透明度50%
	    tl.title('Toplevel Demo')
	    Message(tl, text='This is a prompt by toplevel').pack()
	    
	Button(root, text='Create Toplevel', command=create_tl).pack()
	 
	mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

下边这一系列方法用于与窗口管理器进行交互。他们可以被 Tk(根窗口)进行调用,同样也适用于 Toplevel(顶级窗口)。

注:并非所有操作系统均完全支持下方所有方法的实现。

*aspect(minNumer=None, minDenom=None, maxNumer=None, maxDenom=None)

– 控制该窗口的宽高比(width:height)

– 宽高比限制在:minNumer / minDenom ~ maxNumer / maxDenom

– 如果忽略参数,则返回一个 4 元组表示当前的限制(如果有的话)

*attributes(*args)

– 设置和获取窗口属性

– 如果你只给出选项名,将返回当前窗口该选项的值

– 注意:以下选项不支持关键字参数,*你需要在选项前添加横杠(-)并用字符串的方式表示,用逗号(,)隔开选项和值。

– 例如你希望设置窗口的透明度为 50%,你应该使用 **attribute(“-alpha”, 0.5)代替 attribute(alpha=0.5)

– 下方表格列举了 args 可以使用各个选项的具体含义及用法:

选项含义
alpha

1.(Windows,Mac)控制窗口的透明度

2. 1.0 表示不透明,0.0 表示完全透明

3. 该选项并不支持所有的系统,对于不支持的系统,Tkinter 绘制一个不透明(1.0)的窗口

disabled(Windows)禁用整个窗口(这时候你只能从任务管理器中关闭它)
fullscreen(Windows,Mac)如果设置为 True,则全屏显示窗口
modified(Mac)如果设置为 True,该窗口被标记为改动过
titlepath(Mac)设置窗口代理图标的路径
toolwindow(Windows)如果设置为 True,该窗口采用工具窗口的样式
topmost(Windows,Mac)如果设置为 True,该窗口将永远置于顶层

lient(name=None)

– 设置和获取 WM_CLIENT_MACHINE 属性

– 如果要删除 WM_CLIENT_MACHINE 属性,赋值为空字符串即可

– 该属性仅支持 X 窗口系统的窗口管理器,其他系统均忽略

olormapwindows(*wlist)

– 设置和获取 WM_COLORMAP_WINDOWS 属性

– 该属性仅支持 X 窗口系统的窗口管理器,其他系统均忽略

ommand(value=None)

– 设置和获取 WM_COMMAND 属性

– 该属性仅支持 X 窗口系统的窗口管理器,其他系统均忽略

deiconify()

– 显示窗口

– 默认情况下新创建的窗口都会显示在屏幕上,但使用 iconify() 或 withdraw() 方法可以在屏幕上移除窗口

*focusmodel(model=None)

– 设置和获取焦点模式

*frame()

– 返回一个字符串表示当前系统特征

– 对于类 Unix 系统,返回值是 X 窗口标识符

– 对于 Windows 系统,返回值是 HWND 强制转换为长整形的结果

*geometry(geometry=None)

– 设置和获取窗口的尺寸

– geometry 参数的格式为:“%dx%d+%d+%d” % (width, height, xoffset, yoffset)

*grid(baseWidth=None, baseHeight=None, widthInc=None, heightInc=None)

– 通知窗口管理器该窗口将以网格的形式重新调整尺寸

– baseWidth 和 baseHeight 指定 Tk_GeometryRequest 要求的网格单元数

– widthInc 和 heightInc 指定网格单元的宽度和高度(像素)

*group(window=None)

– 将窗口添加到窗口群中

– window 参数指定控制窗口群的主窗口

– 如果忽略该参数,将返回当前窗口群的主窗口

*iconbitmap(bitmap=None, default=None)

– 设置和获取窗口的图标

– 例如 root.iconbitmap(bitmap=“FishC.ico”)

– default 参数可以用于指定由该窗口创建的子窗口的默认图标

*iconify()

– 将窗口图标化(最小化)

– 需要重新显示窗口,使用 deiconify() 方法

– 该方法会使得 state() 返回 “iconic”

*iconmask(bitmap=None)

– 设置和获取位图掩码

*iconname(newName=None)

– 设置和获取当窗口图标化(最小化)时的图标名字

*iconposition(x=None, y=None)

– 设置和获取当窗口图标化(最小化)时的图标位置

*iconwindow(pathName=None)

– 设置和获取当窗口图标化(最小化)时的组件窗口

– 该方法会使得 state() 返回 “icon”

*maxsize(width=None, height=None)

– 设置和获取该窗口的最大尺寸

*minsize(width=None, height=None)

– 设置和获取该窗口的最小尺寸

*overrideredirect(boolean=None)

– 如果参数为 True,该窗口忽略所有的小部件(也就是说该窗口将没有传统的标题栏、边框等部件)

positionfrom(who=None)

– 指定窗口位置由“谁”决定

– 如果 who 参数是 “user”,窗口位置由用户决定

– 如果 who 参数是 “program”,窗口位置由系统决定

protocol(name=None, func=None)

– 将回调函数 func 与相应的规则 name 绑定

– name 参数可以是 “WM_DELETE_WINDOW”:窗口被关闭的时候

– name 参数可以是 “WM_SAVE_YOURSELF”:窗口被保存的时候

– name 参数可以是 “WM_TAKE_FOCUS”:窗口获得焦点的时候

*resizable(width=None, height=None)

– 指定是否可以改变该窗口的尺寸

– width 为 True 说明允许调整窗口的水平尺寸

– height 为 True 说明允许调整窗口的垂直尺寸

*sizefrom(who=None)

– 指定窗口尺寸由“谁”决定

– 如果 who 参数是 “user”,窗口位置由用户决定

– 如果 who 参数是 “program”,窗口位置由系统决定

*state(newstate=None)

– 设置和获得当前窗口的状态

– newstate 的值可以是 “normal”,“iconic”(见 iconify),“withdrawn”(见 withdraw),“icon”(见 iconwindow)和 “zoomed”(放大,Windows 特有)

*title(string=None)

– 设置窗口的标题

*transient(master=None)

– 指定为 master 的临时窗口

*withdraw()

– 将窗口从屏幕上移除(并没有销毁)

– 需要重新显示窗口,使用 deiconify() 方法

– 该方法会使得 state() 返回 “withdrawn”

Tkinter布局管理

pack, grid, place 均用于管理同在一个父组件下的所有组件的布局,其中:

  • pack 是按添加顺序排列组件
  • grid 是按行/列形式排列组件
  • place 则允许程序员指定组件的大小和位置

Pack:

pack 更适用于少量组件的排列, 使用上比较简单,构建复杂布局可以添加Frame组件或者直接使用grid组件。

注意:不要在同一个父组件中混合使用 pack 和 grid,因为 Tkinter 会很认真地在那儿计算到底先使用那个布局管理器…以至于你等了半个小时,Tkinter 还在那儿纠结不出结果!

pack(**options)

– 下方表格详细列举了各个选项的具体含义和用法:

选项含义
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

EG:

Label(root, text='RED', bg='red', fg='white').pack(fill=X, expand=True)
Label(root, text='GREEN', bg='green', fg='black').pack(fill=X, expand=True)
Label(root, text='BLUE', bg='blue', fg='white').pack(fill=X, expand=True)

Label(root, text='RED', bg='red', fg='white').pack(side=LEFT, expand=True)
Label(root, text='GREEN', bg='green', fg='black').pack(side=LEFT, expand=True)
Label(root, text='BLUE', bg='blue', fg='white').pack(side=LEFT, expand=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述


Grid:

最灵活最值得学习的布局组件,设计对话框so easy!

使用 grid 排列组件,只需告诉它你想要将组件放置的位置(行/列,row 选项指定行,cloumn 选项指定列)。此外,你并不用提前指出网格(grid 分布给组件的位置称为网格)的尺寸,因为管理器会自动计算。

默认情况下组件会居中显示在对应的网格里,你可以使用 sticky 选项来修改这一特性。eg: sticky=W 左对齐

rowspan 和 columnspan 就可以实现跨行和跨列的功能,是的几个网格只放一个组件

– 下方表格详细列举了各个选项的具体含义和用法:

选项含义
column

1. 指定组件插入的列(0 表示第 1 列)

2. 默认值是 0

columnspan指定用多少列(跨列)显示该组件
in_

1. 将该组件放到该选项指定的组件中

2. 指定的组件必须是该组件的父组件

ipadx指定水平方向上的内边距
ipady指定垂直方向上的内边距
padx指定水平方向上的外边距
pady指定垂直方向上的外边距
row指定组件插入的行(0 表示第 1 行)
rowspan指定用多少行(跨行)显示该组件
sticky

1. 控制组件在 grid 分配的空间中的位置

2. 可以使用 N, E, S, W 以及它们的组合来定位(EWSN代表东西南北,上北下南左西右东)

3. 使用加号(+)表示拉长填充,例如 N + S 表示将组件垂直拉长填充网格,N + S + W + E 表示填充整个网格

4. 不指定该值则居中显示

*grid_bbox(column=None, row=None, col2=None, row2=None)

– 返回一个 4 元组描述该组件所在的限定矩形-- 如果指定 column 和 cow 参数,则返回该位置(column, cow)的组件的限定矩形描述

– 如果指定 4 个参数,则返回从(column, cow)到(col2, row2)所有组件的限定矩形描述

– 例如 grid_bbox(0, 0, 1, 1) 返回的是 4 个组件所在的限定矩形

*grid_columnconfigure(index, **options)

– 设置列的属性

– 注意:设置的是该组件所拥有的 grid 的列

– 可以设置的选项及含义如下:

选项含义
minsize指定该列的最小宽度
pad指定该列中最大网格的水平边距
weight

1. 指定列与列之间的相对距离

2. 默认值是 0

3. 这个你比较难理解,小甲鱼还是详细解说下:初创建窗口的时候,grid 会自动根据组件的尺寸分配窗口的尺寸,当你拉伸窗口的尺寸时就会有空白显示出来。这个选项正是指定列与列之间是否填充空白,默认是不填充的。另外,该选项的值是指定填充空白的倍数,例如 weight = 2 的列会比 weight = 1 的列填充多一倍的空白。所以需要平均填充的话,只需要所有的列都设置 weight = 1 即可。

*grid_forget()

– 将组件从屏幕中“删除”

– 并没有销毁该组件,只是看不到了

– 可以通过 grid 或其他布局管理器显示已“删除”的组件,但该组件所在网格的选项设置不会恢复

*grid_info()

– 以字典的形式返回当前 grid 的选项

*grid_location(x, y)

– 返回位于(或接近)给定坐标(x, y)的网格位置

– 返回值是一个 2 元组表示网格对应的(列,行)

*grid_propagate(flag)

– 如果开启,父组件会自动调节尺寸以容纳所有子组件

– 默认值是开启(flag = True)

– 该方法仅适用于父组件

*grid_remove()

– 跟 grid_forget() 一样,但恢复的时候会记住该组件所在网格的选项设置

*grid_rowconfigure(index, **options)

– 设置行的属性

– 注意:设置的是该组件所拥有的 grid 的行

– 可以设置的选项及含义如下:

选项含义
minsize指定该行的最小高度
pad指定该列中最大网格的垂直边距
weight

1. 指定行与行之间的相对距离

2. 默认值是 0

3. 这个你比较难理解,不懂可以参考上边 grid_columnconfigure() 的详细解释

*grid_size()

– 返回该组件所拥有的 grid 的尺寸

– 返回值是一个 2 元组,表示(列, 行)分别的网格数

*grid_slaves(row=None, column=None)

– 以列表的形式返回该组件的所有子组件

– 该方法仅适用于父组件

EG:

Label(root, text='ACCOUNT',).grid(row=0, column=0,sticky=W)
Label(root, text='PASSWORD').grid(row=1, column=0,sticky=W)
Entry(root).grid(row=0, column=1)
Entry(root, show='*').grid(row=1, column=1)
Button(root, text='SUBMIT').grid(columnspan=2)
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述


Place

一般不用,特殊情况有妙用, eg:子组件显示在父组件中间,一个组件覆盖另一个组件

EG:

Label(root, bg='red').place(relx=0.5, rely=0.5, relheight=0.75, relwidth=0.75, anchor=CENTER)

Label(root, bg='yellow').place(relx=0.5, rely=0.5, relheight=0.5, relwidth=0.5, anchor=CENTER)

Label(root, bg='blue').place(relx=0.5, rely=0.5, relheight=0.25, relwidth=0.25, anchor=CENTER)
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

上图无论你如何拉伸改变窗口,三个 Label 的尺寸均会跟着改变(神同步~)。x 和 y 选项用于设置偏移(像素),如果同时设置 relx(rely)和 x(y),那 place 将优先计算 relx 和 rely,然后再实现 x 和 y 指定的偏移值。

– 下方表格详细列举了各个选项的具体含义和用法:

选项含义
anchor

1. 控制组件在 place 分配的空间中的位置

2. N, NE, E, SE, S, SW, W, NW, 或 CENTER 来定位(EWSN代表东西南北,上北下南左西右东)

3. 默认值是 NW

bordermode

1. 指定边框模式(INSIDE 或 OUTSIDE)

2. 默认值是 INSIDE

height指定该组件的高度(像素)
in_

1. 将该组件放到该选项指定的组件中

2. 指定的组件必须是该组件的父组件

relheight

1. 指定该组件相对于父组件的高度

2. 取值范围 0.0 ~ 1.0

relwidth

1. 指定该组件相对于父组件的宽度

2. 取值范围 0.0 ~ 1.0

relx

1. 指定该组件相对于父组件的水平位置

2. 取值范围 0.0 ~ 1.0

rely

1. 指定该组件相对于父组件的垂直位置

2. 取值范围 0.0 ~ 1.0

width指定该组件的宽度(像素)
x

1. 指定该组件的水平偏移位置(像素)

2. 如同时指定了 relx 选项,优先实现 relx 选项

y

1. 指定该组件的垂直偏移位置(像素)

2. 如同时指定了 rely 选项,优先实现 rely 选项

place_forget()

– 将组件从屏幕中“删除”

– 并没有销毁该组件,只是看不到了

– 可以通过 place 或其他布局管理器显示已“删除”的组件

place_info()

– 以字典的形式返回当前 place 的选项

place_slaves()

– 以列表的形式返回该组件的所有子组件

– 该方法仅适用于父组件

17)标准对话框

Tkinter 为了提供了三种标准对话框模块,它们分别是(以前是独立模块,现在全在tkinter下面了):

  • messagebox
  • filedialog
  • colorchooser
    使用时依然要使用from tkinter import messagebox, filedialog, colorchooser

messagebox(消息对话框)

下表为你列出了使用 messagebox 可以创建的所有标准对话框样式:

使用函数
askokcancel(title, message, options)
askquestion(title, message, options)
askretrycancel(title, message, options)
askyesno(title, message, options)
showerror(title, message, options)
showinfo(title, message, options)
showwarning(title, message, options)

参数

所有的这些函数都有相同的参数:

  • title 参数毋庸置疑是设置标题栏的文本
  • message 参数是设置对话框的主要文本内容,你可以用 ‘\n’ 来实现换行
  • options 参数可以设置的选项和含义如下表所示
选项含义
default

1. 设置默认的按钮(也就是按下回车响应的那个按钮)

2. 默认是第一个按钮(像“确定”,“是”或“重试”)

3. 可以设置的值根据对话框函数的不同可以选择:CANCEL,IGNORE,OK,NO,RETRY 或 YES

icon

1. 指定对话框显示的图标

2. 可以指定的值有:ERROR,INFO,QUESTION 或 WARNING

3. 注意:不能指定自己的图标

parent

1. 如果不指定该选项,那么对话框默认显示在根窗口上

2. 如果想要将对话框显示在子窗口 w 上,那么可以设置 parent=w

返回值

askokcancel(),askretrycancel() 和 askyesno() 返回布尔类型的值:

  • 返回 True 表示用户点击了“确定”或“是”按钮
  • 返回 False 表示用户点击了“取消”或“否”按钮

askquestion() 返回“yes”或“no”字符串表示用户点击了“是”或“否”按钮

showerror(),showinfo() 和 showwarning() 返回“ok”表示用户按下了“是”按钮

filedialog(文件对话框)

当你的应用程序需要使用打开文件或保存文件的功能时,文件对话框显得尤为重要。

实现起来就是这样:

from tkinter import *
root = Tk()
def callback():
    fileName = filedialog.askopenfilename()
    print(fileName)
Button(root, text="Open File", command=callback).pack()
mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述

filedialog 模块提供了两个函数:askopenfilename(**option) 和 asksaveasfilename(**option),分别用于打开文件和保存文件。

参数

两个函数可供设置的选项是一样的,下边列举了可用的选项及含义:

选项含义
defaultextension

1. 指定文件的后缀

2. 例如:defaultextension=".jpg",那么当用户输入一个文件名 "FishC" 的时候,文件名会自动添加后缀为 "FishC.jpg"

3. 注意:如果用户输入文件名包含后缀,那么该选项不生效

filetypes

1. 指定筛选文件类型的下拉菜单选项

2. 该选项的值是由 2 元祖构成的列表

3. 每个 2 元祖由(类型名,后缀)构成,例如:filetypes=[("PNG", ".png"), ("JPG", ".jpg"), ("GIF", ".gif")]

initialdir

1. 指定打开/保存文件的默认路径

2. 默认路径是当前文件夹

parent

1. 如果不指定该选项,那么对话框默认显示在根窗口上

2. 如果想要将对话框显示在子窗口 w 上,那么可以设置 parent=w

title指定文件对话框的标题栏文本

返回值

1. 如果用户选择了一个文件,那么返回值是该文件的完整路径

2. 如果用户点击了取消按钮,那么返回值是空字符串

olorchooser(颜色选择对话框)*

颜色选择对话框提供一个友善的界面让用户选择需要的颜色,大家看下例子:

from tkinter import 
root = Tk()
def callback():
  fileName = colorchooser.askcolor()
  print(fileName)

Button(root, text="choose color", command=callback).pack()
mainloop()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

参数

askcolor(color, **option) 函数的 color 参数用于指定初始化的颜色,默认是浅灰色;

option 参数可以指定的选项及含义如下:

选项含义
title指定颜色对话框的标题栏文本
parent

1. 如果不指定该选项,那么对话框默认显示在根窗口上

2. 如果想要将对话框显示在子窗口 w 上,那么可以设置 parent=w

返回值

1. 如果用户选择一个颜色并按下“确定”按钮后,返回值是一个 2 元祖,第 1 个元素是选择的 RGB 颜色值,第 2 个元素是对应的 16 进制颜色值

2. 如果用户按下“取消”按钮,那么返回值是 (None, None)

Tkinter使用多线程

为什么要使用多线程 ==> python之Tkinter使用详解_檬柠wan的博客-CSDN博客_python tkinter

  • 以下为单线程运行

        def interface(self):
            """"界面编写位置"""
            self.Button0 = tk.Button(self.root, text="确定", command=self.event)
            self.Button0.grid(row=0, column=0)
    
            self.w1 = tk.Text(self.root, width=80, height=10)
            self.w1.grid(row=1, column=0)
    
        def event(self):
            '''按钮事件,一直循环'''
            a = 0
            while True:
                a += 1
                self.w1.insert(1.0, str(a)+'\n')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    单线程下,主线程需要运行窗口,如果这个时候点击“确定”按钮,主线程就会去执行event方法,那界面就会出现“无响应”状态,如果要界面正常显示,那我们就需要用到多线程(threading)

    在这里插入图片描述

  • 多线程,完整代码

    import tkinter as tk
    import threading  # 导入多线程模块
    
    
    class GUI:
    
        def __init__(self):
            self.root = tk.Tk()
            self.root.title('演示窗口')
            self.root.geometry("500x200+1100+150")
            self.interface()
    
        def interface(self):
            """"界面编写位置"""
            self.Button0 = tk.Button(self.root, text="确定", command=self.start)
            self.Button0.grid(row=0, column=0)
    
            self.w1 = tk.Text(self.root, width=80, height=10)
            self.w1.grid(row=1, column=0)
    
        def event(self):
            '''按钮事件,一直循环'''
            a = 0
            while True:
                a += 1
                self.w1.insert(1.0, str(a)+'\n')
    
        def start(self):
            self.T = threading.Thread(target=self.event)  # 多线程
            self.T.setDaemon(True)  # 线程守护,即主进程结束后,此线程也结束。否则主进程结束子进程不结束
            self.T.start()  # 启动
    
    
    if __name__ == '__main__':
        a = GUI()
        a.root.mainloop()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    Tkinter多线程暂停和继续

    import tkinter as tk
    import threading
    from time import sleep
    
    event = threading.Event()
    
    
    class GUI:
    
        def __init__(self):
            self.root = tk.Tk()
            self.root.title('演示窗口')
            self.root.geometry("500x200+1100+150")
            self.interface()
    
        def interface(self):
            """"界面编写位置"""
            self.Button0 = tk.Button(self.root, text="启动", command=self.start)
            self.Button0.grid(row=0, column=0)
    
            self.Button0 = tk.Button(self.root, text="暂停", command=self.stop)
            self.Button0.grid(row=0, column=1)
    
            self.Button0 = tk.Button(self.root, text="继续", command=self.conti)
            self.Button0.grid(row=0, column=2)
    
            self.w1 = tk.Text(self.root, width=70, height=10)
            self.w1.grid(row=1, column=0, columnspan=3)
    
        def event(self):
            '''按钮事件,一直循环'''
            while True:
                sleep(1)
                event.wait()
                self.w1.insert(1.0, '运行中'+'\n')
    
        def start(self):
            event.set()
            self.T = threading.Thread(target=self.event)
            self.T.setDaemon(True)
            self.T.start()
    
        def stop(self):
            event.clear()
            self.w1.insert(1.0, '暂停'+'\n')
    
        def conti(self):
            event.set()
            self.w1.insert(1.0, '继续'+'\n')
    
    
    if __name__ == '__main__':
        a = GUI()
        a.root.mainloop()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

Tkinter文件之间的调用

  • 准备工作

    • a.py文件 - -界面逻辑+线程
    • b.py 文件 - -业务逻辑
    • 以上文件在同一个目录下
  • 方法

    # a.py 文件
    import tkinter as tk
    import threading
    from b import logic  # 调用b文件中的logic类
    
    
    class GUI:
        def __init__(self):
            self.root = tk.Tk()
            self.root.title('演示窗口')
            self.root.geometry("500x260+1100+150")
            self.interface()
    
        def interface(self):
            """"界面编写位置"""
            self.Button0 = tk.Button(self.root, text="确定执行", command=self.start, bg="#7bbfea")
            self.Button0.grid(row=0, column=1, pady=10)
    
            self.entry00 = tk.StringVar()
            self.entry00.set("")
    
            self.entry0 = tk.Entry(self.root, textvariable=self.entry00)
            self.entry0.grid(row=1, column=1, pady=15)
    
            self.w1 = tk.Text(self.root, width=50, height=8)
            self.w1.grid(row=2, column=0, columnspan=3, padx=60)
    
        def seal(self):
            '''把b文件的类单独写一个方法'''
            a = self.entry00.get()
            w1 = self.w1
            logic().event(a, w1)
    
        def start(self):
            '''子线程无法直接执行b的类,需要把b文件单独写一个方法,然后执行'''
            self.T = threading.Thread(target=self.seal)
            self.T.setDaemon(True)
            self.T.start()
    
    
    if __name__ == '__main__':
        a = GUI()
        a.root.mainloop()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    # b.py 文件
    import time
    
    
    class logic():
        def __init__(self):
            pass
    
        def main(self, a, x):
            while True:
                y = int(a)+int(x)
                self.w1.insert(1.0, str(y)+'\n')
                time.sleep(1)
                x += 1
    
        def event(self, a, w1):
            '''调用main的方法'''
            self.w1 = w1
            x = 1
            self.main(a, x)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/892415
推荐阅读
相关标签
  

闽ICP备14008679号