tkinter的窗口构建、原生组件放置和监测事件
诸神缄默不语-个人技术博文与视频目录
本文关注用Python3的tkinter包构建GUI窗口,并用tkinter原生组件来进行排版(通过pack()
/ grid()
/ place()
,并监测基础的事件(如按钮被点击后获取文本框输入信息、单/多选框选择结果等)。
最后简单进行一个打包,生成可在其他用户电脑上使用的exe文件(对pyinstaller的更多信息将在未来的博文中详述)
*tkinter原生组件:指tkinter.Label、tkinter.Entry等,而不是tkinter.ttk或ttkbootstrap的组件。虽然事实上这些非原生组件的操作跟原生组件的操作差不多,所以直接套用也区别不大。
文章目录
- 1. 导入包
- 2. 窗口的创建与操作
- 3. 组件
- 1. 组件通用方法
- 4. 布局
- 1. pack
- 2. grid
- 3. place
- 5. 事件监测
- 1. 点击按钮
- 2. 在组件上绑定事件
1. 导入包
import tkinter as tk
from tkinter import messagebox
2. 窗口的创建与操作
tk.Tk对象构成主窗口,当这个主Tk窗口被销毁(destroy()
)时,整个应用程序会退出。
在这个Tk主窗口的基础上可以构建Toplevel子窗口(顶层窗口),这是一个独立于主窗口的窗口,会覆盖在主窗口的前面,常用于显示额外的信息或接收用户的输入。
我们接下来给出的示例就是用软件界面作为主窗口,登录界面作为Toplevel子窗口。打开软件后主窗口隐藏,登录后会销毁子窗口,展示主窗口。
主窗口的构建和隐藏:
root = tk.Tk()
root.title(main_window_title)
root.geometry("500x300")
root.withdraw() # 隐藏
登录界面的构建:
login_window = tk.Toplevel(root)
login_window.title("登录")
login_window.geometry("300x200")
(这里需要注意的是,如果直接这么写的话,在关闭登录窗口后是不会销毁主窗口的,所以应用进程不会自动结束。因为主窗口是隐藏的所以关不了,所以整个进程都关不了了哈,我的解决方案是通过全局布尔变量logged_in来判断当前是否已经完成登录,再构建一个函数on_login_close()
,逻辑是根据logged_in判断关闭登录窗口时是否关闭整个应用:
def on_login_close():"""处理登录窗口关闭事件"""if not logged_in: # 根据登录状态决定是否退出程序root.destroy()else:login_window.destroy()
然后将这个处理登录窗口关闭的函数注册到登录窗口关闭的行为上即可:login_window.protocol("WM_DELETE_WINDOW", on_login_close)
)
窗口常用方法:
title()
geometry()
withdraw()
:隐藏deiconify()
:显示destory()
:销毁protocol()
:注册方法insert(index, chars)
:插入字符get(index1, index2)
:获取字符delete(index1, index2)
:删除字符
3. 组件
第一个参数都是窗口对象或者tk.Frame对象,我就不写了。每个组件下面会简单介绍其入参或实例方法,基本上入参也都是可以在后面的代码中修改的实例属性。
- tk.Label:文本
text:显示文本
fg:字体颜色 - tk.Entry:文本框
show:每个输入文本展示出来的效果,如密码输入框就可以用*
get()
:获取输入文本 - tk.Button:按钮
text:显示文本
command:点击后执行的函数
一个command入参函数示例:def login():username = username_entry.get()password = password_entry.get()if check_account_correct(username, password):root.deiconify() # 显示主窗口login_window.destroy() # 销毁登录窗口else:messagebox.showerror("登录失败", "账号或密码错误!")
- tk.Frame:矩形区域
winfo_children()
:展示所有子组件 - tk.StringVar:一个字符串变量,可以用在动态调整tk.Label显示的文字上,也可以就作为一个变量来作为选择条件……之类的
value - tk.Radiobutton:单选框
text:显示文字
variable
value
command - tk.Listbox:多选框(是比较原始的那种形式,没有点击选择的小方块)
selectmode:可选项:'single'
/tk.SINGLE
,'browse'
/tk.BROWSE
,'multiple'
/tk.MULTIPLE
,'extended'
/tk.EXTENDED
('multiple'
和'extended'
可以通过 Shift/Ctrl 键 + 鼠标点击 实现多选,选中项会高亮显示(如蓝色背景),通过activestyle参数调整
height
activestyle:可选项:'dotbox'
(就是蓝色高亮),'none'
,'underline'
insert(index,*elements)
:插入一个选项。index从0开始,如果直接就想插到最后可以将index设置为'end'
/tk.END
。elements入参可以是一个字符串
selection_set(first: str | int, last: str | int | None = None)
:在不改变当前选项的基础上,将从first到last的所有选项选中
selection_clear(first: str | int, last: str | int | None = None)
:清除从first到last的所有选中
curselection()
:返回选中项的索引,是一个元组对象
get(first, last = None)
:返回first到last的项的值(如果last=None就返回一个值) - tk.Combobox:下拉列表
width
state:normal
可以输入,readonly
只能选择,disabled
不能选择
values:选择列表
set()
:设置默认选项
get()
:获取选择项 - tk.Progressbar:进度条
orient:'horizontal'
,'vertical'
length
mode:'determinate'
,'indeterminate'
1. 组件通用方法
pack_forget()
:从排版上撤回config(key=value)
:设置对象的指定属性的值cget(key)
:返回对象指定属性值
4. 布局
函数就写在组件对象的后面,看下面的例子就知道了。
1. pack
线性布局,就是竖着从上到下一个一个放(在Frame里好像是横着放。这个我也不确定,我再研究一下)。
pack()
可选参数:
- padx、pady、ipadx、ipady
这四个属性分别设置控件水平方向外边距、竖直方向外边距、水平方向内边距、竖直方向内边距。 - side
side属性有四个可选值:'top'
、'bottom'
、'left'
(tk.LEFT
)、'right'
,分别表示将控件位置设在窗口顶部中心、底部中心、左边中心、右边中心。side默认值为'top'
。
登录界面这么构建的话:
tk.Label(login_window, text="账号:").pack()
username_entry = tk.Entry(login_window)
username_entry.pack()tk.Label(login_window, text="密码:").pack()
password_entry = tk.Entry(login_window, show="*")
password_entry.pack()tk.Button(login_window, text="登录", command=login).pack()
最后呈现的效果就会变成这样:
在第二个文本框中输入文字会以星号显示:
点击“登录”按钮即会执行login()
函数。
2. grid
略,待补。
3. place
略,待补。
5. 事件监测
1. 点击按钮
见第3节组件部分的按钮入参command
2. 在组件上绑定事件
widget.bind()
参数:
- sequence
- func(是一个输入为event的函数)
就会组件出现sequence指定的行为时运行func