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"

  • 其中wh表示窗口的宽和高
  • xy表示窗口显示位置的横向和纵向坐标
  • +-则表示正方向还是负方向,基于屏幕左上角为坐标原点,向下或向右为正方向。

扩展

窗口居中的方法

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的流畅。

results matching ""

    No results matching ""