3.1 高级控件学习
控件类 | 名称 | 简要说明 |
LabelFrame | 标签框架 | 带有标签和边框的一个容器,通常用于控件分组 |
Message | 消息框 | 类似于标签,但可以自动换行,用于显示多行文本 |
OptionMenu | 选项菜单 | 即一个下拉菜单 |
Spinbox | 输入控件 | 与Entry类似,但是可以指定输入范围值 |
Menu | 菜单 | 点下菜单按钮后弹出的一个选项列表,用户可以从中选择 |
Listbox | 列表框 | 一个选项列表,用户可以从中选择 |
Scrollbar | 滚动条 | 对其支持的组件(文本域、画布、列表框、文本框)提供滚动功能 |
Text | 多行文本框 | 显示多行文本 |
Toplevel | 顶级窗口 | 它是独立存在的窗口 |
- LabelFrame
- Message
- OptionMenu
- Spinbox
示例代码
from tkinter import *
content = "汉皇重色思倾国,御宇多年求不得。杨家有女初长成,养在深闺人未识。\
天生丽质难自弃,一朝选在君王侧。回眸一笑百媚生,六宫粉黛无颜色。"
root = Tk()
root.geometry("300x400")
top = LabelFrame(root, text="这是 Label")
top.pack(padx=8, pady=8)
# 创建一个Label
Label(top, text=content, bg="yellow").pack()
bottom = LabelFrame(root, text="这是 Message")
bottom.pack(padx=8, pady=8)
# 创建一个Message
Message(bottom, text=content, bg="blue").pack()
# 下拉菜单
op_list = ["选项1", "选项2", "选项3"]
val = StringVar()
val.set(op_list[0])
# 注意,传入的列表前需要加一个*号,这是表示不定参的传递,
# 两个*则是表示字典类型的不定参传递
OptionMenu(root, val, *op_list).pack()
# 指定数字范围
var_range = StringVar()
var_range.set(0)
Spinbox(root, textvariable=var_range, from_=-10, to=10).pack()
# 指定列表范围
Spinbox(root, value=op_list).pack()
root.mainloop()
- Menu
from tkinter import Tk, Menu
root = Tk()
# 创建窗口顶部的菜单栏对象
menu_bar = Menu(root)
# 将菜单栏对象设置给根窗口
root["menu"] = menu_bar # 等价于 root.config(menu=menu_bar)
# 创建“文件”联级菜单
file_menu = Menu(menu_bar, tearoff=0)
# 在菜单栏上添加菜单标签,并将该标签与相应的联级菜单关联起来
menu_bar.add_cascade(label='文件', menu=file_menu)
# 在文件联级菜单中添加菜单项
file_menu.add_command(label='新建', accelerator='Ctrl+N')
file_menu.add_command(label='打开', accelerator='Ctrl+O')
file_menu.add_command(label='保存', accelerator='Ctrl+S')
# 添加分割线
file_menu.add_separator()
file_menu.add_command(label='退出', accelerator='Alt+F4')
about_menu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label='关于', menu=about_menu)
about_menu.add_command(label='关于')
about_menu.add_command(label='帮助')
root.mainloop()
参数说明:
tearoff
菜单项列表中的第一个位置(位置0)会被一个“脱离”元素占用,
tearoff=0
时,菜单将没有脱离功能accelerator
在菜单项名称的右侧显示一个快捷键提示。注意,它只是一个提示,快捷键功能需要监听按键来实现。
- Listbox
- Scrollbar
列表框通常用于数据展示或者作为选项菜单使用。滚动条则是一种辅助的小控件,它通常与列表框或者多行文本框结合使用。
列表框简单示例
from tkinter import *
root = Tk()
list_var = StringVar()
list_var.set(["Go", "Python", "Java", "Dart", "JavaScript"])
Listbox(root, listvariable=list_var, selectmode=BROWSE).pack()
root.mainloop()
参数说明:
selectmode
设置列表框的选择模式。共有四个值,
SINGLE
表示单选,BROWSE
也是单选,但该模式可以通过拖动鼠标来单选,而不仅仅只是点击。MULTIPLE
表示多选,EXTENDED
则表示可以通过拖动鼠标来多选,当然,也可以配合Shift
键通过点击来多选。selectmode
属性默认值是BROWSE
。
结合滚动条示例
from tkinter import *
root = Tk()
list_var = StringVar()
list_var.set(["Go", "Python", "Java", "Dart",
"JavaScript", "C", "C++", "PHPHPHPHPHPHPHPHPHPHPHP"])
# 分别创建x方向、y方向的两个滚动条。orient属性设置其滚动方向
y_bar = Scrollbar(root, orient=VERTICAL)
x_bar = Scrollbar(root, orient=HORIZONTAL)
# 创建列表框
list_box = Listbox(root, yscrollcommand=y_bar.set,
xscrollcommand=x_bar.set,
listvariable=list_var, height=5)
y_bar['command'] = list_box.yview
x_bar['command'] = list_box.xview
# 设置布局方位
y_bar.pack(side=RIGHT, fill=Y)
x_bar.pack(side=BOTTOM, fill=X)
list_box.pack(anchor=NW, fill=BOTH, expand=YES)
root.mainloop()
Listbox
参数说明:
yscrollcommand
列表框纵向滚动时的回调监听,该属性的值是一个回调函数
xscrollcommand
列表框横向滚动时的回调监听。
Scrollbar
参数说明:
command
滚动条拖动时的回调监听,其属性值是一个回调函数
- Text
Text
控件是非常灵活复杂的控件,既可以插入文字,还能插入图片和其他小控件,我们没有必要一次掌握它的全部用法,这里介绍一下基本用法
from tkinter import *
content = "汉皇重色思倾国,御宇多年求不得。杨家有女初长成,养在深闺人未识。" \
"天生丽质难自弃,一朝选在君王侧。回眸一笑百媚生,六宫粉黛无颜色。"
def touch(event):
print(text_area.index(CURRENT))
print(text_area.get(CURRENT, END))
# 清空Text
def clear():
text_area.delete("1.0", END)
root = Tk()
# 创建垂直滚动条
y_bar = Scrollbar(root, orient=VERTICAL)
y_bar.pack(side=RIGHT, fill=Y)
text_area = Text(root, yscrollcommand=y_bar.set, wrap=WORD)
y_bar["command"] = text_area.yview
text_area.bind("<Motion>", touch)
text_area.pack()
# 插入文本内容
text_area.insert(INSERT, content)
text_area.insert('1.0', "这是一句XXX话")
# 插入图片
photo = PhotoImage(file="img.gif")
text_area.image_create(END, image=photo)
# 插入控件
btn = Button(text_area, text="点我", command=clear)
text_area.window_create(END, window=btn)
root.mainloop()
Text的索引
其索引表示比较复杂,有常量,也有字符串,常用的有如下
INSERT
等价于字符串"insert"
,表示当前光标的位置CURRENT
等价于字符串"current"
,当前鼠标所在的位置END
等价于字符串"end"
,表示文本最末的位置line.column
直接指定行列位置,如"1.0"
,表示第一行第一列,注意,行号从1开始,列号从0开始。line.end
指定行末位置,如"1.end"
,表示第一行结尾的位置
不常用的
+ n chars
如"1.0+5c"
,表示在第一行第一列的位置向右移动五个字符的位置linestart
如"current linestart"
,表示当前光标所在行的行首位置
Mark与Tags的简单用法
Mark主要用来控制位置,Tags主要用来改变内容的样式
from tkinter import *
content = "汉皇重色思倾国,御宇多年求不得。杨家有女初长成,养在深闺人未识。" \
"天生丽质难自弃,一朝选在君王侧。回眸一笑百媚生,六宫粉黛无颜色。"
root = Tk()
text_area = Text(root, wrap=WORD)
text_area.pack()
# 插入文本内容
text_area.insert(INSERT, content)
# 创建一个mark
text_area.mark_set('xxx', "1.0")
# 在名为"xxx"的mark处插入文本,第三参数为插入的文本设置一个名为"here_red"的tag
text_area.insert('xxx', "这是一句XXX话", "here_red")
# 设置Tag的样式
text_area.tag_config('here_red', foreground='red')
# 解除mark
text_area.mark_unset("xxx")
# 在指定范围创建一个tag
text_area.tag_add("high_light", "1.50", "1.end")
text_area.tag_config('high_light', background='yellow')
# 在全局删除指定的tag
# text_area.tag_delete("here_red")
# 在指定的范围内删除tag
# text_area.tag_remove("here_red", "1.0", "1.end")
root.mainloop()
- Toplevel
实际上我们的根窗口就是一个顶级窗口。它是独立存在的一个窗口,当我们需要编写多窗口程序或者自定义对话框时,就需要使用它。
简单示例
from tkinter import *
def onclick():
window = Toplevel()
Label(window, text="我是新窗口").pack()
# 设置它所依托的父窗口
window.transient(root)
# 必须调用mainloop,打开一个新窗口后,需要进入新窗口的事件循环
window.mainloop()
root = Tk()
Button(root, text="打开窗口", command=onclick).pack()
root.mainloop()
既然根窗口也是一个顶级窗口,那么顶级窗口的属性和方法,根窗口同样具有。
from tkinter import *
def test(window):
# 让窗口最小化
window.iconify()
# 将最小化的窗口显示出来
# window.deiconify()
# 销毁窗口
# window.destroy()
# 退出mainloop循环
# window.quit()
def onclick():
window = Toplevel()
# 设置窗口出现的位置
window.geometry("+300+300")
window.title("子窗口")
# 该方法传入True时,去除窗口边框
# window.overrideredirect(True)
Button(window, text="点你妹", command=lambda: test(window)).pack()
# 设置所依托的父窗口
# window.transient(root)
# 必须要加上此行,打开一个新窗口后,必须进入新窗口的事件循环
window.mainloop()
root = Tk()
# 设置窗口标题
root.title("主窗口")
# 设置窗口的宽高与显示的位置
root.geometry("300x200+200+200")
# 固定窗口的长宽,不可改变窗口大小(width=None, height=None)
root.resizable(False, False)
# 设置窗口小图标(必须位于geometry与resizable方法之后)
root.iconbitmap("tools.ico")
Button(root, text="打开窗口", command=onclick).pack()
root.mainloop()
关于geometry
的参数设置
该方法需要传入一个固定格式的字符串,格式:"wxh±x±y"
- 其中
w
、h
表示窗口的宽和高 x
、y
表示窗口显示位置的横向和纵向坐标+
、-
则表示正方向还是负方向,基于屏幕左上角为坐标原点,向下或向右为正方向。
扩展
窗口居中的方法
from tkinter import *
root = Tk()
# 获取当前根窗口的宽、高
cur_width = root.winfo_width()
cur_height = root.winfo_height()
# 获取电脑屏幕的宽、高
scn_width, scn_height = root.maxsize()
# 窗口显示的坐标拼接成固定格式字符串
tmpcnf = '+%d+%d' % ((scn_width-cur_width)/2, (scn_height-cur_height)/2)
root.geometry(tmpcnf)
# 固定窗口的长宽,不可改变窗口大小(width=None, height=None)
root.resizable(False, False)
Label(root, text="我是标签", bg="yellow").pack(side=LEFT)
Button(root, text="这是按钮").pack(side=LEFT)
root.mainloop()
注意,当窗口大小不固定时,是通过动态获取根窗口的宽高来计算位置,如果窗口的宽高一开始就是确定的,请使用确定值,尽量避免动态获取窗口的大小,以免影响GUI的流畅。