Python Tkinter GUI框架深度解析

什么是Tkinter

Tkinter 是 Python 的标准 GUI(图形用户界面)库。它是 Python 内置的一个模块,用于创建桌面应用程序的用户界面。Tkinter 基于 Tcl(脚本语言)/Tk(GUI工具包) 库,是 Python 提供的默认图形界面开发工具。因为它与 Python 一起分发,所以不需要单独安装,使用时只需要导入相应的模块即可。

Tkinter的跨平台性

Tkinter 可以在多个操作系统上运行,包括 Windows、macOS 和 Linux。

Python的图形用户界面

在 Python 中,有许多库可以用来创建客户端 GUI(图形用户界面)。以下是一些常见的 Python GUI 库和框架:

  • Tkinter:

  • 描述: Tkinter 是 Python 的标准 GUI 库,基于 Tk GUI 工具包。
  • 特点: 内置于 Python 标准库中,易于上手,适合快速开发简单的 GUI 应用。
  • PyQt:

  • 描述: PyQt 是 Qt 库的 Python 绑定,提供了强大的跨平台 GUI 开发能力。
  • 特点: 功能丰富,支持多种平台,适合开发复杂的应用。
  • PySide:

  • 描述: PySide 是 Qt 库的另一种 Python 绑定,和 PyQt 类似,但采用了不同的许可证(LGPL)。
  • 特点: 与 PyQt 类似,支持多平台,适合开发专业级应用。
  • Kivy:

  • 描述: Kivy 是一个用于开发跨平台应用的开源 Python 库,支持触控界面。
  • 特点: 适用于移动设备和桌面应用,支持多种输入方式。
  • wxPython:

  • 描述: wxPython 是 wxWidgets C++ 库的 Python 绑定,提供了原生的 GUI 组件。
  • 特点: 提供原生界面外观,支持多平台。
  • FLTK (Fast, Light Toolkit):

  • 描述: FLTK 是一个轻量级的 C++ GUI 工具包,Python 有 FLTK 的绑定库 pyFLTK
  • 特点: 轻量且高效,适合对资源要求高的应用。
  • Dear PyGui:

  • 描述: Dear PyGui 是一个用于创建简单而高性能 GUI 的库,特别适用于游戏和图形应用。
  • 特点: 直观的 API 和高性能渲染。
  • PyGTK:

  • 描述: PyGTK 是 GTK+ 的 Python 绑定,适用于 Linux 系统上的图形用户界面。
  • 特点: 主要用于 Linux 系统,支持 GNOME 桌面环境。
  • 在众多 Python GUI 库中,PyQtTkinter 是两个最为常用且功能强大的库。

    Tkinter的组件

    1. 顶层窗口 (Toplevel Window)

  • Tk: 主窗口,一个顶级窗口。
  • Toplevel: 创建一个子窗口,类似于 Tk 同样是个顶级窗口,但作为主窗口的子窗口存在。
  • 2. 基本控件 (Basic Widgets)

  • Label: 标签,用于显示文本或图像。
  • Button: 按钮,用户可以点击以触发事件。
  • Canvas: 画布,允许绘制图形、显示图像、创建图形界面或其他小部件。
  • Entry: 单行文本输入框,用户可以输入文本。
  • Text: 多行文本框,用于显示和编辑多行文本。
  • Frame: 框架,用于包含其他小部件的容器。
  • LabelFrame: 带标题的框架,作为 Frame 的扩展。
  • PhotoImage: 用于显示图片(仅限 GIF 和 PGM/PPM 格式)。
  • 3. 容器控件 (Container Widgets)

  • Frame: 用作其他控件的容器。
  • LabelFrame: 类似于 Frame,但带有标签。
  • PanedWindow: 可调节大小的窗口容器,包含多个子窗口。
  • Notebook: 选项卡式窗口容器。
  • 4. 选择控件 (Selection Widgets)

  • Checkbutton: 复选按钮,用于多选。
  • Radiobutton: 单选按钮,用于单选。
  • Scale: 滑块,用于选择数值。
  • Spinbox: 数值选择框,允许用户选择或输入数值。
  • 5. 菜单控件 (Menu Widgets)

  • Menu: 菜单栏,包含多个菜单项。
  • MenuButton: 菜单按钮,点击后显示下拉菜单。
  • 6. 列表控件 (List Widgets)

  • Listbox: 列表框,显示一个或多个项目的列表。
  • Scrollbar: 滚动条,与其他控件一起使用来提供滚动功能。
  • 7. 对话框控件 (Dialog Widgets)

  • Message: 信息对话框,显示多行不可编辑文本。
  • MessageBox: 用于显示消息对话框,如信息、警告、错误等。
  • FileDialog: 文件对话框,用于打开或保存文件。
  • ColorChooser: 颜色选择对话框,用户可以选择颜色。
  • SimpleDialog: 简单对话框,用于用户输入。
  • 8. 高级控件 (Advanced Widgets)

  • Treeview: 树视图,用于显示分层数据。
  • Progressbar: 进度条,显示任务的进度。
  • Combobox: 组合框,类似于下拉列表。
  • 9. 定制与布局控件 (Customization and Layout Widgets)

  • Place: 绝对定位管理器,允许精确控制组件位置。
  • Pack: 包装定位管理器,按顺序排列组件。
  • Grid: 网格定位管理器,在表格中排列组件。
  • 颜色选项

  • 标准颜色名称:如 "red""blue""green""yellow" 等。
  • 十六进制颜色代码:如 "#FF5733"(橙红色)、"#4CAF50"(绿色)。
  • RGB 颜色代码:格式为 "#RRGGBB",其中 RRGGBB 是红色、绿色、蓝色的分量(例如 "#0000FF" 表示蓝色)。
  • 事件绑定选项

  • "<Button-1>" 鼠标左键点击
  • "<Button-2>": 鼠标中键点击
  • "<Button-3>": 鼠标右键点击
  • "<Double-1>": 鼠标左键双击
  • "<Enter>": 鼠标光标进入组件
  • "<Leave>": 鼠标光标离开组件
  • "<Configure>": 窗口或组件大小发生变法时触发
  • "<KeyRelease>": 键盘随便一个按键松开时触发
  • "<Control-z>": 按下Ctrl+z事件
  • 布局管理器

    pack() 相对布局管理器

    pack 布局管理器按顺序将小部件放入父容器中,通常是垂直或水平的。

    参数详细说明:

  • side: 指定小部件在父容器中的哪一侧放置。可以是以下值:

  • TOP: 放置在顶部(默认值)
  • BOTTOM: 放置在底部
  • LEFT: 放置在左侧
  • RIGHT: 放置在右侧
  • anchor:指定组件在其可用空间内的对齐方式。该属性在组件没有完全填满其分配的空间时生效
  • 取值:'n'、'ne'、'e'、'se'、's'、'sw'、'w'、'nw'、'center'(默认值为'center')。
  • ┌─────────────────────┐
    │        n            │
    │    nw      ne       │
    │ w     center    e   │
    │    sw      se       │
    │        s            │
    └─────────────────────┘
    
  • fill: 指定小部件如何填充其父容器的空间。可以是以下值:

  • NONE: 不填充(默认值)
  • X: 仅在水平方向填充
  • Y: 仅在垂直方向填充
  • BOTH: 在水平方向和垂直方向都填充
  • expand: 一个布尔值,指定小部件是否应在父容器中扩展以填补额外的空间。True 使小部件扩展,False 不扩展(默认值)。

  • padxpady: 控制小部件与父容器边界之间的水平和垂直间距。可以是单个值或两个值(分别用于 x 和 y 方向)。

  • ipadx 和 ipady:设置组件的内部填充(padding),即组件内容与边框之间的间距。ipadx用于水平内边距,ipady用于垂直内边距,默认值为0。

  • grid() 网格布局管理器

    grid 布局管理器通过网格系统在父容器中定位小部件。

    参数详细说明:

  • row: 指定小部件所在的行(从 0 开始)。

  • column: 指定小部件所在的列(从 0 开始)。

  • rowspan: 指定小部件跨越的行数。

  • columnspan: 指定小部件跨越的列数。

  • sticky: 指定小部件在单元格中的对齐方式。可以是以下值:

  • N: 顶部对齐
  • S: 底部对齐
  • E: 右侧对齐
  • W: 左侧对齐
  • NS: 垂直方向对齐
  • EW: 水平方向对齐
  • NEWS: 四个方向都对齐
  • padxpady: 控制小部件与单元格边界之间的水平和垂直间距。

  • ipadxipady: 控制小部件的内部填充,即小部件内部内容与小部件边界之间的水平和垂直间距。

  • place() 绝对布局管理器

    place 布局管理器使用绝对定位或相对定位将小部件放置在其父容器中。

    参数详细说明:

  • xy: 指定小部件的绝对坐标位置(相对于父容器的左上角)。

  • relxrely: 指定小部件的相对坐标位置(0 到 1 之间的值,表示父容器的相对位置)。

  • anchor: 指定小部件在位置坐标处的对齐方式。可以是以下值之一:

  • N, E, S, W 等,表示方位的缩写(北、东、南、西)
  • bordermode: 指定小部件的边界模式,控制小部件位置计算是否考虑边框。可以是以下值:

  • INSIDE: 位置计算不包括边框
  • OUTSIDE: 位置计算包括边框
  • widthheight: 指定小部件的宽度和高度。

  • relwidthrelheight: 指定小部件的相对宽度和高度(0 到 1 之间的值,表示父容器的相对大小)。

  • 组件的使用

    Tk主窗口组件

    Tk 是创建应用程序主窗口的顶层容器。

    Tk组件常用方法

    1. 窗口管理方法

  • withdraw(): 隐藏窗口,但不销毁它。
  • deiconify(): 显示一个已被withdraw()方法隐藏的窗口。
  • iconify(): 最小化窗口。
  • state(): 返回窗口的状态(如'normal''iconic''withdrawn'等)。
  • wm_state(state=None): state()方法的别名,也可以用来设置窗口状态。
  • 2. 尺寸和位置方法

  • geometry(newGeometry=None): 获取或设置窗口的大小和位置(例如"200x100+10+20")。
  • maxsize(width=None, height=None): 获取或设置窗口的最大尺寸。
  • minsize(width=None, height=None): 获取或设置窗口的最小尺寸。
  • resizable(width=None, height=None): 获取或设置窗口的大小是否可变(水平和垂直方向)。
  • positionfrom(who=None): 设置窗口位置的参考点。
  • sizefrom(who=None): 设置窗口大小的参考来源。
  • 3. 标题和图标方法

  • title(string=None): 获取或设置窗口的标题。
  • iconbitmap(bitmap=None): 设置窗口的图标。
  • iconphoto(default=False, *args): 设置窗口的图标照片。
  • 4. 透明度和样式方法

  • attributes(*args): 获取或设置窗口的多种属性(如透明度、是否置顶等)。
  • wm_attributes(*args): 与attributes()方法相同,用于管理窗口属性。
  • transient(master=None): 将窗口设置为临时窗口,使其在另一个窗口的上方。
  • 5. 事件处理方法

  • bind(sequence=None, func=None, add=None): 绑定事件处理程序。
  • unbind(sequence, funcid=None): 解除事件处理程序的绑定。
  • bind_all(sequence=None, func=None, add=None): 对所有窗口控件绑定事件处理程序。
  • bind_class(className, sequence=None, func=None, add=None): 对特定控件类绑定事件处理程序。
  • event_add(virtual, *sequences): 添加虚拟事件。
  • event_delete(virtual, *sequences): 删除虚拟事件。
  • event_generate(sequence, **kw): 生成事件。
  • event_info(virtual=None): 获取有关事件的信息。
  • 6. 退出和销毁方法

  • destroy(): 销毁当前窗口及其当前窗口的所有子窗口。
  • quit(): 退出主事件循环。
  • 7. 其他常用方法

  • tkraise(aboveThis=None): 提升窗口的堆叠顺序。
  • lift(aboveThis=None): 提升窗口的堆叠顺序,tkraise()的别名。
  • lower(belowThis=None): 降低窗口的堆叠顺序。
  • Tk示例

    1. 有图标有标题的的Tk主窗口

    import tkinter as tk
    
    root = tk.Tk()
    root.title("主窗口")  # 设置窗口标题
    root.geometry("300x200")  # 设置窗口大小
    
    # 设置图标。图片格式
    icon = tk.PhotoImage(file="static/icon/a.png")
    root.iconphoto(False, icon)
    
    root.mainloop()  # 进入事件循环

    2. 设置主窗口在桌面居中打开

    import tkinter as tk
    
    
    # 窗口居中方法
    def center_window(window, width, height):
        # 获取屏幕宽度和高度
        screen_width = window.winfo_screenwidth()
        screen_height = window.winfo_screenheight()
    
        # 计算窗口的x和y坐标,使窗口居中
        x = (screen_width - width) // 2
        y = (screen_height - height) // 2
    
        # 设置窗口的大小和位置
        window.geometry(f'{width}x{height}+{x}+{y}')
    
    
    root = tk.Tk()
    root.title("主窗口")  # 设置窗口标题
    
    # 设置窗口大小并居中显示
    window_width = 300
    window_height = 200
    center_window(root, window_width, window_height)
    
    root.mainloop()  # 进入事件循环
    

    3. 设置窗口透明度

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("透明度的窗口")
    
    # 设置窗口大小
    root.geometry("300x200")
    
    # 设置窗口透明度(范围从 0.0 到 1.0,1.0 表示完全不透明)
    root.wm_attributes('-alpha', 0.5)
    
    # 进入主事件循环
    root.mainloop()

    4. 主窗口设置背景图片,图片随着窗口大小的变化动态变化

    import tkinter as tk
    from PIL import Image, ImageTk
    
    
    def resize_image(image, size):
        """调整图片大小以适应指定的尺寸"""
        return image.resize(size, Image.LANCZOS)
    
    
    def update_background(event):
        """在窗口调整大小时更新背景图片"""
        global background_photo
        new_width = root.winfo_width()
        new_height = root.winfo_height()
    
        # 调整图片大小以填充窗口
        resized_image = resize_image(background_image, (new_width, new_height))
        background_photo = ImageTk.PhotoImage(resized_image)
    
        # 更新标签显示的图片
        background_label.config(image=background_photo)
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("动态背景图片窗口")
    
    # 设置窗口初始大小
    window_width = 500
    window_height = 350
    root.geometry(f'{window_width}x{window_height}')
    
    # 使用 Pillow 加载背景图片
    background_image = Image.open("static/background/a.png")
    
    # 创建初始背景图片
    initial_resized_image = resize_image(background_image, (window_width, window_height))
    background_photo = ImageTk.PhotoImage(initial_resized_image)
    
    # 创建标签以显示背景图片
    background_label = tk.Label(root, image=background_photo)
    background_label.place(x=0, y=0, relwidth=1, relheight=1)
    
    # 绑定窗口大小变化事件
    root.bind('<Configure>', update_background)
    
    # 进入主事件循环
    root.mainloop()
    

    5. 主窗口设置背景颜色

    import tkinter as tk
    
    root = tk.Tk()
    root.title("设置主窗口背景颜色")
    root.geometry("300x200")
    
    # 设置主窗口的背景颜色
    root.configure(bg="lightblue")
    # root.configure(bg="#0000AF")
    
    root.mainloop()
    


    Button按钮组件

    Button组件常用方法

    创建 Button 按钮

    button = tk.Button(root, text="点击我", command=on_button_click)

  • root 是按钮的父容器。
  • text 设置按钮上显示的文本。
  • command 设置按钮被点击时调用的函数,这里是 on_button_click
  • 设置按钮的颜色

    button = tk.Button(root, text="点击我", command=on_button_click, bg="blue", fg="white")

  • bg 是按钮的背景颜色。也可以使用十六进制#0000FF这样的
  • fg 是按钮的文本颜色。
  • 设置按钮的字体

    button = tk.Button(root, text="点击我", command=on_button_click, font=("Arial", 14, "bold"))

  • font 设置字体和大小加粗
  • 设置按钮的大小

    button = tk.Button(root, text="点击我", command=on_button_click, width=15, height=2)

    button = tk.Button(root, text="点击我", command=on_button_click, padx=20, pady=5)

  • width 按钮的宽
  • height 按钮的高
  • padx 通过修改内边距修改按钮的宽
  • padx 通过修改内边距修改按钮的高
  • 设置按钮的状态

    button = tk.Button(root, text="点击我", command=on_button_click, state=tk.DISABLED)

  • state=tk.DISABLED 按钮不可点击
  • 使用图片作为按钮

    img = tk.PhotoImage(file="path_to_image.png")
    button = tk.Button(root, image=img, command=on_button_click)

    Button按钮的布局管理器

    pack() 布局管理器

  • pack() 布局管理器用于将控件按顺序放置在主窗口中。它的布局方式是将控件打包到容器的顶部、底部、左侧或右侧,也可以让控件在容器中居中对齐。
  • grid() 布局管理器

  • grid() 布局管理器将控件放置在一个网格中,通过指定行和列的位置来安排控件。这适用于需要精确布局的情况。
  • place 布局管理器

  • place() 布局管理器允许你通过指定绝对或相对位置来放置控件。这种方法提供了最大的灵活性,但需要你手动计算位置。
  • Button示例

    1. 创建一个button有点击事件

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Tkinter Button 示例")
    root.geometry("300x200")
    
    
    # 定义按钮点击事件的回调函数
    def on_button_click():
        print("按钮被点击了!")
    
    
    # 创建一个按钮
    button = tk.Button(root, text="点击我", command=on_button_click)
    
    # 放置按钮到主窗口
    button.pack(padx=20, pady=20)
    
    # 运行主循环
    root.mainloop()
    

    2. pack() 布局管理器

    import tkinter as tk
    
    root = tk.Tk()
    root.title("pack 布局管理器示例")
    root.geometry("300x200")
    
    # 创建按钮并使用 pack() 布局
    button1 = tk.Button(root, text="按钮上")
    button1.pack(side=tk.TOP, padx=10, pady=10)
    
    button2 = tk.Button(root, text="按钮左")
    button2.pack(side=tk.LEFT, padx=10, pady=10)
    
    button3 = tk.Button(root, text="按钮右")
    button3.pack(side=tk.RIGHT, padx=10, pady=10)
    
    button4 = tk.Button(root, text="按钮下")
    button4.pack(side=tk.BOTTOM, padx=10, pady=10)
    
    root.mainloop()

    3. grid() 布局管理器

    import tkinter as tk
    
    root = tk.Tk()
    root.title("grid 布局管理器示例")
    root.geometry("300x200")
    
    # 创建按钮并使用 grid() 布局
    button1 = tk.Button(root, text="第一行第一列")
    button1.grid(row=0, column=0, padx=10, pady=10)
    
    button2 = tk.Button(root, text="第一行第二列")
    button2.grid(row=0, column=1, padx=10, pady=10)
    
    button3 = tk.Button(root, text="第二行第一列")
    button3.grid(row=1, column=0, padx=10, pady=10)
    
    button4 = tk.Button(root, text="第二行第二列")
    button4.grid(row=1, column=1, padx=10, pady=10)
    
    root.mainloop()
    

    4. place() 布局管理器 写xy坐标

    import tkinter as tk
    
    root = tk.Tk()
    root.title("place 布局管理器示例")
    root.geometry("300x200")
    
    # 创建按钮并使用 place() 布局
    button1 = tk.Button(root, text="按钮1")
    button1.place(x=20, y=20)
    
    button2 = tk.Button(root, text="按钮2")
    button2.place(x=100, y=20)
    
    button3 = tk.Button(root, text="按钮3")
    button3.place(x=20, y=100)
    
    button4 = tk.Button(root, text="按钮4")
    button4.place(x=100, y=100)
    
    root.mainloop()
    

    5. 按钮的边框设置

  • tk.RAISED:按钮看起来有一个向上凸起的效果,边框会有阴影效果,使按钮突出。
  • tk.SUNKEN:按钮看起来有一个向下凹陷的效果,边框有内阴影效果,使按钮看起来被压入背景中。
  • tk.FLAT:按钮没有边框的立体效果,边框是平的,看起来像没有边框。
  • tk.GROOVE:按钮的边框看起来像是有一个凹槽效果,边框看起来凹陷。
  • tk.RIDGE:按钮的边框看起来像是有一个凸起的脊线效果,形成一个明显的边界。
  • import tkinter as tk
    
    root = tk.Tk()
    root.title("Relief 示例")
    root.geometry("300x350")
    
    # 创建不同样式的按钮
    button_raised = tk.Button(root, text="Raised", relief=tk.RAISED, width=15, height=2)
    button_sunken = tk.Button(root, text="Sunken", relief=tk.SUNKEN, width=15, height=2)
    button_flat = tk.Button(root, text="Flat", relief=tk.FLAT, width=15, height=2)
    button_groove = tk.Button(root, text="Groove", relief=tk.GROOVE, width=15, height=2)
    button_ridge = tk.Button(root, text="Ridge", relief=tk.RIDGE, width=15, height=2)
    
    # 放置按钮
    button_raised.pack(padx=10, pady=10)
    button_sunken.pack(padx=10, pady=10)
    button_flat.pack(padx=10, pady=10)
    button_groove.pack(padx=10, pady=10)
    button_ridge.pack(padx=10, pady=10)
    
    root.mainloop()
    

    6. 按钮悬停改变颜色

    import tkinter as tk
    
    
    def on_enter(event):
        button.config(bg="#FF0000", text="悬停中")  # 悬停时修改背景颜色和文本
    
    
    def on_leave(event):
        button.config(bg="#71B960", text="未悬停")  # 悬停时恢复背景颜色和文本
    
    
    root = tk.Tk()
    root.title("按钮悬停效果示例")
    root.geometry("300x200")
    
    # 创建一个按钮
    button = tk.Button(
        root,
        text="未悬停",
        bg="#71B960",
        fg="white",
        padx=20,
        pady=5
    )
    
    # 绑定悬停事件
    button.bind("<Enter>", on_enter)
    button.bind("<Leave>", on_leave)
    
    button.pack(padx=20, pady=20)
    
    root.mainloop()
    

     

    7. 图片当作按钮

    import tkinter as tk
    from PIL import Image, ImageTk
    
    def create_resized_image(image_path, size):
        # 打开图像
        image = Image.open(image_path)
        # 调整图像大小
        image = image.resize(size, Image.LANCZOS)
        # 转换为 PhotoImage 对象
        return ImageTk.PhotoImage(image)
    
    root = tk.Tk()
    root.title("调整图像大小的按钮示例")
    root.geometry("300x200")  # 窗口的大小
    
    # 设置按钮大小
    button_size = (120, 60)  # 例如:宽度 120 像素,高度 60 像素
    
    # 载入并调整图像大小
    photo = create_resized_image("static/icon/b.png", button_size)  # 替换为你的图像路径
    
    # 创建一个按钮并设置图像
    button = tk.Button(
        root,
        
        text="图像按钮",        # 文本内容
        compound=tk.CENTER,     # 图像和文本的组合方式
        fg="white",             # 文本颜色
        
        image=photo,            # 图片
        borderwidth=0,          # 去除按钮边框, 点击时看不到边框
        relief=tk.FLAT,         # 边框是平的,看起来像没有边框
    )
    
    button.pack(padx=20, pady=20)
    
    root.mainloop()
    


    Toplevel子窗口组件

    Toplevel组件常用方法

  • title():设置或获取窗口的标题。
  • geometry():设置或获取窗口的尺寸和位置。
  • resizable():设置窗口是否可以调整大小。
  • configure():配置窗口的各种选项,如背景色、字体等。
  • transient():将窗口标记为某个窗口的临时窗口,通常用于对话框。
  • grab_set():捕获所有的用户输入,直到窗口被销毁或调用 grab_release()。
  • wait_window():阻塞主循环,直到窗口被销毁。
  • destroy():销毁窗口,关闭窗口并释放资源。
  • withdraw():隐藏窗口而不是销毁它,可以稍后使用 deiconify() 恢复显示。
  • iconbitmap():设置窗口的图标。
  • protocol():设置窗口关闭时的处理方法,例如添加自定义的处理函数。
  • focus_set():设置窗口为当前活动窗口,使其获得焦点。
  • Toplevel组件示例

    1. 打开一个子窗口

    import tkinter as tk
    
    
    def open_new_window():
        # 创建新的 Toplevel 窗口
        new_window = tk.Toplevel(root)
        new_window.title("子窗口")
        new_window.geometry("250x150")
    
        # 在新窗口中添加一些控件
        label = tk.Label(new_window, text="这是一个子窗口")
        label.pack(padx=20, pady=20)
    
        button = tk.Button(new_window, text="Close", command=new_window.destroy)
        button.pack(pady=10)
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("主窗口")
    root.geometry("300x200")
    
    # 在主窗口中添加一个按钮,点击后打开新的 Toplevel 窗口
    open_button = tk.Button(root, text="打开子窗口", command=open_new_window)
    open_button.pack(padx=20, pady=20)
    
    # 运行应用程序
    root.mainloop()
    

    2. 打开一个子窗口,传递参数到子窗口

    import tkinter as tk
    
    def open_new_window(param1, param2):
        # 创建新的 Toplevel 窗口
        new_window = tk.Toplevel(root)
        new_window.title("子窗口")
        new_window.geometry("250x150")
    
        # 在新窗口中添加一些控件
        label = tk.Label(new_window, text="这是一个子窗口")
        label.pack(padx=10, pady=10)
    
        # 在 Toplevel 窗口中创建一个标签显示传递的参数
        label = tk.Label(new_window, text=f"参数1: {param1}, 参数二: {param2}")
        label.pack(padx=10, pady=10)
    
        button = tk.Button(new_window, text="Close", command=new_window.destroy)
        button.pack(pady=10)
    
    # 创建主窗口
    root = tk.Tk()
    root.title("主窗口")
    root.geometry("300x200")
    
    # 在主窗口中添加一个按钮,点击后打开新的 Toplevel 窗口
    open_button = tk.Button(root, text="打开子窗口", command=lambda: open_new_window("Hello", "Toplevel"))
    open_button.pack(padx=20, pady=20)
    
    # 运行应用程序
    root.mainloop()
    

    3. 子窗口打开时不能操作主窗口

    import tkinter as tk
    
    def open_new_window():
        # 创建新的 Toplevel 窗口
        new_window = tk.Toplevel(root)
        new_window.title("子窗口")
        new_window.geometry("250x150")
    
        # 不能操作主窗口
        new_window.grab_set()
    
        # 在新窗口中添加一些控件
        label = tk.Label(new_window, text="这是一个子窗口")
        label.pack(padx=20, pady=20)
    
        button = tk.Button(new_window, text="Close", command=new_window.destroy)
        button.pack(pady=10)
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("主窗口")
    root.geometry("300x200")
    
    # 在主窗口中添加一个按钮,点击后打开新的 Toplevel 窗口
    open_button = tk.Button(root, text="打开子窗口", command=open_new_window)
    open_button.pack(padx=20, pady=20)
    
    # 运行应用程序
    root.mainloop()
    

    4. 捕获窗口关闭事件

    import tkinter as tk
    
    
    def open_window_with_protocol():
        def on_closing():
            print("子窗口关闭了")
            window.destroy()
    
        window = tk.Toplevel(root)
        window.title("子窗口")
        window.geometry("250x150")
    
        # 设置关闭窗口的协议
        window.protocol("WM_DELETE_WINDOW", on_closing)
    
        # 添加控件到窗口
        label = tk.Label(window, text="这是一个子窗口")
        label.pack(pady=20)
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("主窗口")
    root.geometry("300x200")
    
    # 添加按钮以打开窗口
    protocol_button = tk.Button(root, text="打开子窗口", command=open_window_with_protocol)
    protocol_button.pack(pady=20)
    
    root.mainloop()
    

    Label显示文本或图片组件

    Label组件常用选项

  • text: 标签显示的文本内容。
  • font: 设置文本的字体、大小等(例如 ("Arial", 16))。
  • fg: 设置文本颜色(例如 "blue")。
  • bg: 设置标签背景颜色(例如 "lightyellow")。
  • width: 标签的宽度(以字符数为单位)。
  • height: 标签的高度(以字符数为单位)。
  • anchor: 文本对齐方式(例如 "w" 表示左对齐, "e"右对齐"center"居中)。
  • padx: 文本和标签边缘之间的水平间距。
  • pady: 文本和标签边缘之间的垂直间距。
  • image: 显示图像(需要 PhotoImageBitmapImage 对象)。
  • compound: 文本和图像的组合方式。
  • top: 图片在上,文字在下。
  • bottom: 图片在下,文字在上。
  • left: 图片在左,文字在右。
  • right: 图片在右,文字在左。
  • center: 图片和文字重叠(默认值)。
  • Label组件示例

    1. 创建一个Label组件,显示文本

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Label 示例")
    root.geometry("300x200")
    
    # 创建一个标签组件
    label = tk.Label(root, text="Hello, Tkinter!", font=("Arial", 16), fg="blue", bg="lightyellow")
    
    # 使用 pack 布局管理器放置标签
    label.pack(padx=20, pady=20)
    
    # 运行主事件循环
    root.mainloop()
    

    2. 文本太长,自动换行

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("自动换行示例")
    root.geometry("300x200")
    
    # 创建 Label,设置宽度和自动换行
    label = tk.Label(root, text="这是一个很长的文本,它会根据指定的宽度自动换行显示。", wraplength=150)
    label.pack()
    
    # 运行主事件循环
    root.mainloop()
    

    3. 带边框和内间距间隔

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("设置边框和填充示例")
    root.geometry("300x200")
    
    # 创建 Label,设置边框宽度和填充
    label = tk.Label(root, text="带边框和填充的标签", borderwidth=1, relief="solid", padx=10, pady=10)
    label.pack()
    
    # 运行主事件循环
    root.mainloop()

    4. Label的点击事件

    import tkinter as tk
    
    # 定义点击事件处理程序
    def on_label_click(event):
        print("Label clicked!")
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Label 点击事件示例")
    root.geometry("300x200")
    
    # 创建标签组件
    label = tk.Label(root, text="Click me!")
    label.pack(padx=20, pady=20)
    
    # 绑定鼠标左键点击事件(<Button-1> 代表左键点击)
    label.bind("<Button-1>", on_label_click)
    
    # 运行主事件循环
    root.mainloop()
    

    5. 显示图片

    import tkinter as tk
    from PIL import Image, ImageTk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Label 显示 JPEG 图片示例")
    
    # 加载 JPEG 图片
    image = Image.open("static/background/a.jpg")
    photo = ImageTk.PhotoImage(image)
    
    # 创建 Label 并设置图片
    label = tk.Label(root, image=photo)
    label.pack(padx=20, pady=20)
    
    # 保持对 Image 和 PhotoImage 的引用,防止被垃圾回收
    label.image = photo
    
    # 运行主事件循环
    root.mainloop()
    

    6. 显示图片,图片大小不超过Label组件大小,图片不变形百分比缩放

    import tkinter as tk
    from PIL import Image, ImageTk
    
    
    def resize_image(image, max_width, max_height):
        # 获取图像的原始尺寸
        original_width, original_height = image.size
    
        # 计算调整后的宽度和高度
        ratio = min(max_width / original_width, max_height / original_height)
        new_width = int(original_width * ratio)
        new_height = int(original_height * ratio)
    
        # 调整图像大小
        return image.resize((new_width, new_height), Image.LANCZOS)
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Label 显示图片并调整大小示例")
    root.geometry("300x200")
    
    # 设置 Label 的最大大小,百分比缩放
    label_width = 300
    label_height = 200
    
    # 加载原始图片
    original_image = Image.open("static/background/a.jpg")
    
    # 调整图片大小以适应 Label
    resized_image = resize_image(original_image, label_width, label_height)
    photo = ImageTk.PhotoImage(resized_image)
    
    # 创建 Label 并设置初始图片
    label = tk.Label(root, image=photo, width=label_width, height=label_height)
    label.pack(padx=20, pady=20)
    
    # 保持对 PhotoImage 对象的引用
    label.image = photo
    
    # 运行主事件循环
    root.mainloop()
    

    7. 图片和文字都显示的组合

    import tkinter as tk
    from PIL import Image, ImageTk
    
    
    def resize_image(image, max_width, max_height):
        # 获取图像的原始尺寸
        original_width, original_height = image.size
    
        # 计算调整后的宽度和高度
        ratio = min(max_width / original_width, max_height / original_height)
        new_width = int(original_width * ratio)
        new_height = int(original_height * ratio)
    
        # 调整图像大小
        return image.resize((new_width, new_height), Image.LANCZOS)
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Label 显示图片并调整大小示例")
    root.geometry("300x200")
    
    # 设置 Label 的最大大小,百分比缩放
    label_width = 100
    label_height = 120
    
    # 加载原始图片
    original_image = Image.open("static/background/a.jpg")
    
    # 调整图片大小以适应 Label
    resized_image = resize_image(original_image, label_width, label_height)
    photo = ImageTk.PhotoImage(resized_image)
    
    # 创建 Label 并设置初始图片
    label = tk.Label(root, text="头像", compound="bottom", font=("Arial", 14), image=photo, width=label_width,
                     height=label_height)
    label.pack(padx=20, pady=20)
    
    # 保持对 PhotoImage 对象的引用
    label.image = photo
    
    # 运行主事件循环
    root.mainloop()
    


    Entry单行文本输入框组件

    Entry组件常用方法

    1. 基本方法

  • delete(first, last=None): 删除文本框中从 firstlast 位置的字符。如果只提供 first 参数,则删除该位置的单个字符。常用值包括:

  • 0tkinter.END:删除所有内容。
  • get(): 返回文本框中当前的内容(文本)。

  • insert(index, string): 在指定的 index 位置插入文本 string

  • index(index): 返回光标位置或索引位置,index 可以是数字、"end""insert" 等。

  • icursor(index): 设置插入光标的位置,index 指定位置。

  • xview(*args): 控制文本框的水平滚动。常用于和水平滚动条 (Scrollbar) 配合使用。

  • 2. 文本选择相关方法

  • select_adjust(index): 根据指定索引调整当前文本选择的范围。

  • select_clear(): 取消当前文本选择。

  • select_from(index): 从指定的 index 位置开始选择文本。

  • select_present(): 检查当前是否有文本被选择,如果有则返回 True,否则返回 False

  • select_range(start, end): 选择从 startend 位置的文本。

  • select_to(index): 选择从文本框开始到指定的 index 位置的文本。

  • 3. 光标和视图控制方法

  • see(index): 滚动文本框以确保指定的 index 位置可见。

  • mark_set(mark, index): 设置一个标记(例如插入光标位置)到指定的 index 位置。

  • mark_unset(mark): 删除指定名称的标记。

  • 4. 配置和属性方法

  • config(**options)configure(**options): 更改或获取 Entry 的配置选项,如字体、背景颜色、文本颜色等。

  • cget(option): 获取指定配置选项的当前值。

  • 5. 状态检查方法

  • instate(statespec, callback=None, *args, **kw): 如果状态匹配指定的 statespec,则调用回调函数。

  • state(statespec=None): 获取或设置当前小部件的状态(如 "disabled"、"normal" 等)。

  • 6. 绑定和事件方法

  • bind(sequence, func, add=None): 绑定一个事件到文本框。例如,<Return> 可以绑定到一个回调函数来处理回车键事件。

  • bind_all(sequence, func, add=None): 绑定一个事件到所有的文本框组件。

  • bind_class(className, sequence, func, add=None): 绑定一个事件到所有属于该类的文本框组件。

  • unbind(sequence, funcid=None): 解除绑定事件。

  • Entry组件示例

    1. 创建 Entry 组件

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("tkinter Entry 使用示例")
    root.geometry("300x200")
    
    # 创建标签
    label = tk.Label(root, text="请输入您的名字:")
    label.pack(pady=10)
    
    # 创建 Entry 输入框并设置默认文本
    entry = tk.Entry(root)
    entry.insert(0, "请输入...")  # 设置默认文本
    # 设置输入框宽度
    entry.config(width=30)
    entry.pack(pady=5)
    
    # 运行主循环
    root.mainloop()
    

    2. 限制最多输入字符数量

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("tkinter Entry 使用示例")
    root.geometry("300x200")
    
    # 定义最大字符数
    MAX_CHARACTERS = 20
    
    # 定义验证函数
    def validate_input(text):
        return len(text) <= MAX_CHARACTERS
    
    # 创建验证命令
    validate_cmd = root.register(validate_input)
    
    # 创建标签
    label = tk.Label(root, text="请输入您的名字:")
    label.pack(pady=10)
    
    # 创建 Entry 输入框并设置默认文本
    entry = tk.Entry(root, validate="key", validatecommand=(validate_cmd, "%P"))
    entry.insert(0, "请输入...")
    entry.config(width=30)
    entry.pack(pady=5)
    
    # 运行主循环
    root.mainloop()
    

    3. 设置背景颜色

    entry = tk.Entry(root, bg="lightyellow")  # 设置背景色为浅黄色

    4. 去除边框

    entry = tk.Entry(root, borderwidth=0, relief="flat")

    5. 输入框颜色与主窗口背景颜色保持一致

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("tkinter Entry 背景色与主窗口一致")
    root.geometry("300x200")
    
    # 设置主窗口背景色
    root_bg_color = "#f0f0f0"  # 主窗口背景色
    
    # 设置主窗口的背景色
    root.config(bg=root_bg_color)
    
    # 创建标签
    label = tk.Label(root, text="请输入您的名字:", bg=root_bg_color)
    label.pack(pady=10)
    
    # 创建 Entry 输入框
    entry = tk.Entry(root, borderwidth=0, relief="flat", bg=root_bg_color, fg="black")  # 背景色与主窗口一致,文本色为黑色
    entry.insert(0, "请输入...")
    entry.config(width=30)
    entry.pack(pady=5)
    
    # 运行主循环
    root.mainloop()
    

    6. 输入框只显示下边框,宽度和窗口一样宽

    import tkinter as tk
    
    
    def create_entry_with_bottom_border(parent):
        # 创建一个包含 Entry 和下边框的 Frame
        frame = tk.Frame(parent, bg="black")
    
        # 创建 Entry 输入框
        frame_entry = tk.Entry(frame, borderwidth=0, relief="flat", bg=root_bg_color)
    
        # 重要:fill=tk.X 输入框水平填充满Frame,此时输入框大小和frame大小一致,设置输入宽高失效
        # ---- pady=(0, 2):下划线的高度
        frame_entry.pack(padx=0, pady=(0, 2), fill=tk.X)
    
        frame.pack(padx=10, pady=10, fill=tk.X)  # 确保 Frame 宽度填充主窗口
    
        return frame_entry
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("tkinter Entry 只有下边框")
    root.geometry("300x200")
    
    # 设置主窗口背景色
    root_bg_color = "#f0f0f0"  # 主窗口背景色
    root.config(bg=root_bg_color)
    
    # 创建标签
    label = tk.Label(root, text="请输入您的名字:", bg=root_bg_color)
    label.pack(pady=10)
    
    # 使用自定义函数创建带有下边框的 Entry
    entry = create_entry_with_bottom_border(root)
    entry.insert(0, "请输入...")  # 设置默认文本
    
    # 运行主循环
    root.mainloop()
    

    7. 输入框只显示下边框,指定输入框的宽高

    import tkinter as tk
    
    
    def create_entry_with_bottom_border(parent, width, height):
        # 创建一个包含 Entry 和下边框的 Frame
        frame = tk.Frame(parent, bg="black", width=width, height=height)
        frame.pack_propagate(False)  # 防止 Frame 调整其大小以适应内部控件
    
        # 创建 Entry 输入框
        frame_entry = tk.Entry(frame, borderwidth=0, relief="flat", bg=root_bg_color)
    
        # 重要:fill=tk.BOTH, expand=True 输入框水平垂直全部填充满Frame,
        # ---- 此时输入框大小和frame大小一致,设置输入宽高失效,
        # ---- pady=(0, 2):下划线的高度
        frame_entry.pack(padx=0, pady=(0, 2), fill=tk.BOTH, expand=True)
    
        frame.pack(padx=10, pady=10)
    
        return frame_entry
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("tkinter Entry 只有下边框")
    root.geometry("300x200")
    
    # 设置主窗口背景色
    root_bg_color = "#f0f0f0"  # 主窗口背景色
    root.config(bg=root_bg_color)
    
    # 创建标签
    label = tk.Label(root, text="请输入您的名字:", bg=root_bg_color)
    label.pack(pady=10)
    
    # Entry 输入框的宽高
    entry_width = 180
    entry_height = 20
    
    # 使用自定义函数创建带有下边框的 Entry
    entry = create_entry_with_bottom_border(root, entry_width, entry_height)
    entry.insert(0, "请输入...")  # 设置默认文本
    
    # 运行主循环
    root.mainloop()
    

    8. 获取输入框内容,清空输入框内容

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("tkinter Entry 使用示例")
    root.geometry("300x200")
    
    # 创建标签
    label = tk.Label(root, text="请输入您的名字:")
    label.pack(pady=10)
    
    # 创建 Entry 输入框并设置默认文本
    entry = tk.Entry(root)
    entry.insert(0, "请输入姓名...")  # 设置默认文本
    entry.pack(pady=5)
    
    # 设置输入框宽度
    entry.config(width=30) 
    
    # 定义获取 Entry 内容的函数
    def get_entry_content():
        content = entry.get()
        if content == "" or content == "请输入姓名...":
            result_label.config(text="请先输入内容!")
        else:
            print("Entry 内容:", content)
            result_label.config(text="当前内容: " + content)
    
    # 定义清除 Entry 内容的函数
    def clear_entry_content():
        entry.delete(0, tk.END)
        result_label.config(text="Entry 内容已清除")
        entry.insert(0, "请输入姓名...")  # 重新设置默认文本
    
    # 定义事件处理函数:点击输入框清除默认文本
    def on_entry_click(event):
        if entry.get() == "请输入姓名...":
            entry.delete(0, tk.END)  # 清空输入框内容
    
    # 绑定点击事件到输入框
    entry.bind("<Button-1>", on_entry_click)
    
    # 创建按钮来获取 Entry 内容
    get_button = tk.Button(root, text="获取内容", command=get_entry_content)
    get_button.pack(pady=5)
    
    # 创建按钮来清除 Entry 内容
    clear_button = tk.Button(root, text="清除内容", command=clear_entry_content)
    clear_button.pack(pady=5)
    
    # 显示当前内容的标签
    result_label = tk.Label(root, text="")
    result_label.pack(pady=10)
    
    # 运行主循环
    root.mainloop()
    


    Text多行文本输入框组件

    Text组件常用属性

  • height: 设置 Text 组件的行数(高度),即可见的文本行数。

  • width: 设置 Text 组件的列数(宽度),即可见的字符数。

  • bgbackground: 设置文本框的背景颜色。

  • fgforeground: 设置文本的前景颜色(文本颜色)。

  • font: 设置文本的字体和大小。例如,"Helvetica 12"

  • wrap: 设置文本的换行模式。可能的值有 "word"(按单词换行)和 "char"(按字符换行)。

  • undo: 设置是否启用撤销功能(布尔值)。

  • state: 设置 Text 组件的状态,可以是 "normal"(正常编辑)、"disabled"(禁用编辑)或 "hidden"(隐藏文本)。

  • insertbackground: 设置插入符(光标)的颜色。

  • spacing1: 设置段落顶部的额外行间距,单位像素。

  • spacing2: 设置行与行之间的额外行间距,单位像素。没有文字和文字水平间距。

  • spacing3: 设置段落底部的额外行间距,单位像素。

  • tabs: 设置制表符的间距。

  • selectbackground: 设置选中文本的背景颜色。

  • selectforeground: 设置选中文本的前景颜色。

  • insertborderwidth: 设置插入符的边框宽度。

  • padxpady: 设置文本框内容的内边距(水平和垂直方向)。

  • Text组件常用方法

    1. 基础文本操作

  • insert(index, text, *tags): 在指定的 index 位置插入文本,可以选择性地添加标签。
  • delete(index1, index2=None): 删除从 index1index2 的文本。如果没有提供 index2,只删除 index1 处的一个字符。
  • get(index1, index2=None): 获取从 index1index2 的文本。如果没有提供 index2,只获取 index1 处的一个字符。
  • replace(index1, index2, text): 替换从 index1index2 的文本为新的 text
  • 2. 索引和位置操作

  • index(index): 返回 index 的标准格式。
  • search(pattern, index, *options): 在文本中搜索模式 pattern,从 index 开始。可以使用 regexp 选项进行正则表达式搜索。
  • 3. 选区和剪贴板

  • tag_add(tagName, index1, index2=None): 在指定的文本范围(从 index1index2)内添加一个标签。
  • tag_remove(tagName, index1, index2=None): 从指定的文本范围(从 index1index2)内移除一个标签。
  • tag_config(tagName, **options): 配置标签的属性,如字体、颜色等。
  • tag_names(index=None): 返回在指定 index 位置存在的所有标签。
  • tag_ranges(tagName): 返回具有指定 tagName 的所有文本范围。
  • tag_delete(tagName): 删除指定的标签。
  • tag_bind(tagName, sequence, function, add=None): 绑定事件处理器到指定的标签。
  • tag_unbind(tagName, sequence, funcid=None): 解除标签上绑定的事件。
  • 4. 格式化和外观

  • mark_set(markName, index): 设置或移动名为 markName 的标记到指定的 index
  • mark_unset(markName): 删除指定的标记。
  • mark_names(): 返回所有标记的列表。
  • mark_next(index): 返回紧跟 index 之后的标记名称。
  • mark_previous(index): 返回紧接在 index 之前的标记名称。
  • mark_gravity(markName, direction): 设置标记的重力方向("left" 或 "right")。
  • 5. 滚动和视图

  • see(index): 确保指定的 index 位置可见。
  • yview(*args): 控制文本组件的垂直滚动。
  • xview(*args): 控制文本组件的水平滚动。
  • 6. 控件状态

  • config(**options): 配置文本组件的各种选项。
  • cget(option): 获取文本组件的指定选项的当前值。
  • focus_set(): 将输入焦点设置到文本组件。
  • focus_get(): 获取当前具有输入焦点的控件。
  • bind(sequence, func, add=None): 将事件绑定到控件。
  • 7. 底层交互

  • clipboard_get(type='STRING'): 从剪贴板获取内容。
  • clipboard_append(text, **kw): 将文本追加到剪贴板。
  • clipboard_clear(): 清除剪贴板内容。
  • 8. 执行命令

  • edit_undo(): 撤销上一个操作(如果启用了撤销)。
  • edit_redo(): 重做上一个操作(如果启用了撤销)。
  • edit_reset(): 重置撤销和重做堆栈。
  • edit_separator(): 在撤销堆栈中插入一个分隔符。
  • edit_modified(arg=None): 获取或设置修改标志。
  • Text组件示例

    1. 创建一个 Text 组件,高度为 5 行,宽度为 20 列

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Text Widget Example")
    root.geometry("300x200")
    
    # 创建一个 Text 组件
    text_widget = tk.Text(root, height=5, width=20)
    text_widget.pack()
    
    # 运行主循环
    root.mainloop()
    

    2. 插入和删除文本内容

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Text Widget Example")
    root.geometry("300x200")
    
    # 创建一个 Text 组件,高度为 5 行,宽度为 20 列
    text_widget = tk.Text(root, height=5, width=20)
    text_widget.pack()
    
    # 插入文本
    text_widget.insert(tk.END, "Hello, Tkinter!\n")
    text_widget.insert(tk.END, "这是一个文本组件.哈哈哈哈")
    
    # 删除文本,从第1行的第0个字符到第1行的第5个字符
    text_widget.delete("1.0", "1.5")
    
    # 运行主循环
    root.mainloop()

    3. 获取文本内容

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Text Widget Example")
    root.geometry("300x200")
    
    # 创建一个 Text 组件,高度为 5 行,宽度为 20 列
    text_widget = tk.Text(root, height=5, width=20)
    text_widget.pack()
    
    # 插入文本
    text_widget.insert(tk.END, "这是一个文本组件.哈哈哈哈")
    
    # 获取文本内容
    all_text = text_widget.get(1.0, tk.END)
    print(all_text)
    
    # 运行主循环
    root.mainloop()

    4. 插入带格式的文本

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Text")
    root.geometry("300x200")
    
    # 创建一个 Text 组件,高度为 5 行,宽度为 20 列
    text_widget = tk.Text(root, height=5, width=20)
    text_widget.pack()
    
    # 插入带标签的文本
    text_widget.insert(tk.END, "红色加粗文本\n", "bold_red")
    # 配置标签的样式
    text_widget.tag_config("bold_red", foreground="red", font=("Helvetica", 12, "bold"))
    
    # 插入带有背景色的文本
    text_widget.insert(tk.END, "背景色文本\n", "highlight")
    # 配置另一个标签的样式
    text_widget.tag_config("highlight", background="yellow")
    
    # 运行主循环
    root.mainloop()
    

    5. 带滚动条的多行文本框

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Text")
    root.geometry("300x200")
    
    # 创建一个 Frame 来容纳 Text 和 Scrollbar
    frame = tk.Frame(root)
    frame.pack(padx=10, pady=10)
    
    # 创建 Text 组件
    text_widget = tk.Text(frame, height=5, width=20, wrap="none")
    text_widget.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)  # text 显示在左边,垂直水平全部扩展
    
    # 创建一个垂直滚动条,并将其放置在 Text 组件的内部
    scrollbar = tk.Scrollbar(frame, command=text_widget.yview, bg="red")  # 滚动条和text垂直滑动绑定
    scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
    
    # 将 Text 组件与滚动条进行绑定 yscrollcommand:垂直滚动条
    text_widget.config(yscrollcommand=scrollbar.set)
    
    # 插入一些文本内容以便演示
    for i in range(1, 100):
        text_widget.insert(tk.END, f"Line {i}\n")
    
    # 运行主循环
    root.mainloop()
    

    6. 启用、禁用文本输入

    # 禁用文本输入
    text_widget.config(state=tk.DISABLED)
    
    # 启用文本输入
    text_widget.config(state=tk.NORMAL)
    

    7. 获取文本光标位置

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Text Widget Example")
    root.geometry("300x200")
    
    # 创建一个 Text 组件
    text_widget = tk.Text(root, height=5, width=20)
    text_widget.pack()
    
    text_widget.insert(tk.END, "哈哈")
    
    # 获取当前光标位置
    cursor_index = text_widget.index(tk.INSERT)
    print(f"光标下标: {cursor_index}")
    
    # 在光标当前位置插入文本
    text_widget.insert(cursor_index, "abcdef")
    
    # 运行主循环
    root.mainloop()
    

    8. 绑定Ctrl+z撤销事件,一次一次的撤销,长按一直撤销

    import tkinter as tk
    
    
    def on_undo(event):
        print("撤销上一次操作")
        text_widget.edit_undo()
    
    
    def on_key_press(event):
        # 在每次按键后插入一个撤销分隔符,使每个字符成为独立的撤销步骤
        text_widget.edit_separator()
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Text 撤销")
    root.geometry("300x200")
    
    # 创建一个 Text 组件
    text_widget = tk.Text(root, height=5, width=20)
    text_widget.pack()
    
    # 启用撤销和重做功能
    text_widget.config(undo=True)
    
    # 取消上一次撤销的操作,用Control-y绑定,这里就不演示了
    # text_widget.edit_redo()
    
    # 绑定 Ctrl+z 撤销按钮事件
    text_widget.bind("<Control-z>", on_undo)
    # 绑定键盘按钮松开事件,让每输入一个字符成为独立的操作,一次撤销时只能撤销一个字符
    text_widget.bind("<KeyRelease>", on_key_press)
    
    # 运行主循环
    root.mainloop()
    

    9. 替换文本

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Text 搜索和替换")
    root.geometry("300x200")
    
    # 创建一个 Text 组件
    text_widget = tk.Text(root, height=5, width=20)
    text_widget.insert(tk.END, "Hello World!")
    text_widget.pack()
    
    # 搜索的文本
    search_text = "World"
    # 替换的文本
    replace_text = "Tkinter"
    
    # 搜索文本并获取其位置
    start_pos = text_widget.search(search_text, "1.0", tk.END)
    print(f"Found 'example' at: {start_pos}")
    
    # 替换文本
    if start_pos:
        end_pos = f"{start_pos}+{len('World')}c"
        text_widget.delete(start_pos, end_pos)
        text_widget.insert(start_pos, replace_text)
    
    # 运行主循环
    root.mainloop()
    

    Frame内嵌框架组件

    Frame组件常用方法

    1. 方法和功能

  • __init__(self, master=None, cnf={}, **kwargs): 用于初始化一个 Frame 实例。master 参数指定父容器,cnfkwargs 用于设置其他属性。

  • pack(side=TOP, fill=BOTH, expand=NO, padx=0, pady=0, anchor=CENTER, before=None, after=None): 用于将 Frame 放置到父容器中,按指定的布局选项进行包装。

  • grid(row=0, column=0, sticky=N+S+E+W, padx=0, pady=0, columnspan=1, rowspan=1, ipadx=0, ipady=0, padx=0, pady=0): 用于将 Frame 放置到父容器中的网格布局中,指定行、列和其他布局参数。

  • place(x=0, y=0, anchor='nw', bordermode='inside', relx=0.0, rely=0.0, relwidth=1.0, relheight=1.0, width=None, height=None): 用于将 Frame 放置在父容器中的指定位置,支持绝对和相对位置设置。

  • pack_propagate(False): pack布局时,是否自动调整大小以适应内部组件。

  • grid_propagate(False): grid布局时,是否自动调整大小以适应内部组件。

  • config(**kwargs): 用于更新 Frame 的配置选项,类似于 configure 方法。

  • cget(option): 用于获取 Frame 的指定选项的当前值。

  • configure(**kwargs): 用于设置 Frame 的选项,如 backgroundborderwidth 等。

  • destroy(): 销毁 Frame,并移除其所有子控件。

  • update(): 更新 Frame 的显示,通常在修改 Frame 的配置后调用。

  • update_idletasks(): 更新 Frame 的空闲任务队列,确保所有挂起的任务(如布局调整)被处理。

  • unbind(sequence=None, funcid=None): 解除与指定事件序列相关联的回调函数。

  • bind(sequence=None, func=None, add=None): 将指定事件序列绑定到回调函数,使得事件发生时调用该函数。

  • forget(): 从布局管理器中移除 Frame,但不会销毁 Frame 或其子控件。

  • wait_variable(variable): 等待指定的 Tkinter 变量的值发生变化。

  • wait_window(window): 等待指定的窗口(通常是对话框)关闭。

  • 2. 常见配置选项

  • backgroundbg: 设置 Frame 的背景颜色。
  • borderwidthbd: 设置 Frame 的边框宽度。
  • relief: 设置 Frame 的边框样式(如 flatraisedsunkengrooveridge)。
  • 3. 布局管理

  • pack(): 控制控件的排列方式。
  • grid(): 控制控件的网格布局。
  • place(): 控制控件的位置和大小。
  • Frame组件示例

    1. 创建一个固定大小的 Frame 

    import tkinter as tk
    
    root = tk.Tk()
    root.title("Frame 框架")
    root.geometry("300x200")
    
    # 创建第一个 Frame
    frame = tk.Frame(root, bg="lightgray", width=150, height=100)
    frame.pack_propagate(False)  # 防止 Frame 调整其大小以适应内部控件
    frame.place(x=20, y=20)
    
    label1 = tk.Label(frame, text="Frame")
    label1.pack(padx=10, pady=10)
    
    root.mainloop()
    

    2. 在 Frame 框架中来排列组件 Grid 布局

    import tkinter as tk
    
    root = tk.Tk()
    root.title("Grid Layout in Frame")
    root.geometry("300x200")
    
    # 创建一个 Frame
    frame = tk.Frame(root)
    frame.pack(padx=10, pady=10)
    
    # 在 Frame 中使用 grid 布局。 sticky="e":右侧对齐
    tk.Label(frame, text="姓名:").grid(row=0, column=0, padx=5, pady=5, sticky="e")
    tk.Entry(frame).grid(row=0, column=1, padx=5, pady=5)
    tk.Label(frame, text="年龄:").grid(row=1, column=0, padx=5, pady=5, sticky="e")
    tk.Entry(frame).grid(row=1, column=1, padx=5, pady=5)
    # columnspan:跨越2列
    tk.Button(frame, text="提交").grid(row=2, column=0, columnspan=2, pady=10)
    
    root.mainloop()
    

    3. Pack 布局,平分父窗口

    import tkinter as tk
    
    root = tk.Tk()
    root.title("Frames with Pack Layout")
    root.geometry("300x200")
    
    # 创建第一个 Frame
    frame1 = tk.Frame(root, bg="lightblue")
    frame1.pack(fill=tk.BOTH, expand=True)  # fill=tk.BOTH 水平垂直方向填充,expand=True外部也填充占满整父窗口
    
    label1 = tk.Label(frame1, text="This is Frame 1")
    label1.pack(pady=10)
    
    # 创建第二个 Frame
    frame2 = tk.Frame(root, bg="lightgreen")
    frame2.pack(fill=tk.BOTH, expand=True)
    
    label2 = tk.Label(frame2, text="This is Frame 2")
    label2.pack(pady=10)
    
    root.mainloop()
    

    4. Place 布局,xy坐标指定位置

    import tkinter as tk
    
    root = tk.Tk()
    root.title("Place Layout Example")
    root.geometry("300x200")
    
    # 创建一个 Frame
    frame = tk.Frame(root, width=200, height=100, bg="lightyellow")
    frame.place(x=50, y=50)
    
    # 在 Frame 中放置控件
    tk.Label(frame, text="This is a frame with 'place' layout", bg="lightyellow").place(x=20, y=20)
    tk.Button(frame, text="Click Me").place(x=20, y=60)
    
    root.mainloop()
    

    5. Frame 传递参数

    import tkinter as tk
    
    
    def create_frame(parent, bg_color, width, height, name):
        frame = tk.Frame(parent, bg=bg_color, width=width, height=height)
        frame.pack_propagate(False)
        frame.pack(padx=10, pady=10)
        tk.Label(frame, text=name).pack(pady=10)
        return frame
    
    
    root = tk.Tk()
    root.title("Frame 传递参数")
    root.geometry("300x200")
    
    # 创建 Frame 使用函数
    create_frame(root, "lightgreen", 200, 100, "参数一 Hello")
    
    create_frame(root, "lightcoral", 300, 150, "参数二 Frame")
    
    root.mainloop()
    

    6. Frame 右侧打开一个详情页

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("右侧详情页")
    root.geometry("300x200")  # 设置窗口大小
    
    # 在窗口右侧动态添加Frame
    def add_frame():
        # 创建一个新的 Frame
        new_frame = tk.Frame(root, bg='lightblue', width=150)
        new_frame.pack_propagate(False)
        new_frame.pack(side=tk.RIGHT, fill=tk.Y)
    
        # 当前Frame没关闭,不能操作主窗口
        new_frame.grab_set()
    
        tk.Label(new_frame, text="我是详情页", bg='lightblue').pack(pady=40)
    
        # 关闭详情页
        tk.Button(new_frame, text="关闭", command=new_frame.destroy).pack()
    
    # 打开详情页按钮
    add_frame_button = tk.Button(root, text="打开详情页", command=add_frame)
    add_frame_button.place(x=120, y=50)
    
    # 运行主循环
    root.mainloop()
    


    LabelFrame内嵌框架组件

    LabelFrame 和 Frame 一样,只是多了一个标题,用来区域分组。LabelFrame的相关方法和用法请到查看Frame查看。

    LabelFrame 和 Frame 的区别

    Frame

  • 作用:Frame 是一个简单的容器控件,用于将其他控件分组在一起。它本身没有任何视觉效果,主要用于组织和管理布局。
  • 用法:通常用来创建应用程序的布局,或者用作容器来分组和组织控件。
  • LabelFrame

  • 作用LabelFrameFrame 的一种特殊形式,它除了作为容器外,还提供了一个标签(文字)作为标题。这个标签通常显示在框架的顶部,并且可以用于描述或命名框架中的控件。
  • 用法:通常用来创建具有标题的分组区域,可以使界面更具结构性和可读性。
  • LabelFrame示例

    import tkinter as tk
    
    root = tk.Tk()
    root.title("LabelFrame")
    root.geometry("500x200")
    
    # 创建一个Frame,用来放两个LabelFrame
    frame1 = tk.Frame(root)
    frame1.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
    
    labelframe1 = tk.LabelFrame(frame1, text="分组一", padx=10, pady=10)
    labelframe1.pack(padx=10, pady=0, fill="both", expand=True)
    
    labelframe2 = tk.LabelFrame(frame1, text="分组二", padx=10, pady=10)
    labelframe2.pack(padx=10, pady=10, fill="both", expand=True)
    
    # 创建第二个Frame,用来放两个LabelFrame
    frame2 = tk.Frame(root)
    frame2.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
    
    labelframe3 = tk.LabelFrame(frame2, text="分组三", padx=10, pady=10)
    labelframe3.pack(padx=10, pady=0, fill="both", expand=True)
    
    labelframe4 = tk.LabelFrame(frame2, text="分组四", padx=10, pady=10)
    labelframe4.pack(padx=10, pady=10, fill="both", expand=True)
    
    root.mainloop()
    


    Canvas画布组件

    Canvas组件常用方法

    创建 Canvas 对象

  • canvas = Canvas(parent, width=200, height=100)
  • parent 是 Canvas 的父组件(通常是 Tk 或 Frame)。
  • width 和 height 是画布的宽度和高度。
  • 绘制直线

  • canvas.create_line(x1, y1, x2, y2, options…)
  • 绘制从 (x1, y1)(x2, y2) 的直线。
  • 绘制矩形

  • canvas.create_rectangle(x1, y1, x2, y2, options…)
  • 绘制一个矩形,左上角坐标为 (x1, y1),右下角坐标为 (x2, y2)
  • 绘制椭圆形

  • canvas.create_oval(x1, y1, x2, y2, options…)
  • 绘制一个椭圆,包围矩形的区域是 (x1, y1)(x2, y2)
  • 绘制多边形

  • canvas.create_polygon(x1, y1, x2, y2, …, options…)
  • 绘制一个由多个顶点组成的多边形。
  • 绘制文本

  • canvas.create_text(x, y, text="文本", options…)
  • (x, y) 位置绘制文本。
  • 绘制图像

  • canvas.create_image(x, y, image=image, options…)
  • (x, y) 位置显示图像,其中 image 是一个 PhotoImageBitmapImage 对象。
  • 绘制图形时的参数说明

  • canvas.create_*(x1, y1, x2, y2, fill, outline, width, font)
  • fill: 设置图形的填充颜色,例如 fill='red'
  • outline: 设置图形的边框颜色,例如 outline='black'
  • width: 设置图形的边框宽度,例如 width=2
  • font: 设置文本的字体,例如 font=('Helvetica', 12)
  • 获取图形标签

  • tags = canvas.gettags(tag_or_id)
  • 获取图形的标签。
  • 删除图形

  • canvas.delete(tag_or_id)
  • 删除指定 ID 或标签的图形。ID通过create_*方法会返回一个图形的唯一 ID。
  • 移动图形

  • canvas.move(tag_or_id, x, y)
  • 将指定 ID 或标签的图形移动 (x, y) 像素。
  • 调整图形属性

  • canvas.itemconfig(tag_or_id, option=value)
  • 调整图形的属性,如颜色、字体等。
  • 获取或设置图形位置

  • coords = canvas.coords(tag_or_id)
  • 取指定图形的坐标信息。
  • 画布事件绑定

  • canvas.bind("<Button-1>", callback_function)
  • 绑定鼠标左键单击事件到 callback_function
  • 画布解绑事件

  • canvas.unbind("<Button-1>")
  • 解绑鼠标左键单击事件。
  • 图形事件绑定

  • canvas.tag_bind(tag, sequence, callback)
  • 绑定事件序列到标签 tag 的图形项上,并指定回调函数 callback
  • 图形事件解绑

  • canvas.tag_unbind(tag, sequence)
  • 解除标签 tag 上的事件序列的绑定。
  • 缩放图形

  • canvas.scale(tag_or_id, x, y, scale_x, scale_y)
  • (x, y) 为中心缩放指定 ID 或标签的图形项,按比例 scale_xscale_y
  • 旋转图形

  • canvas.rotate(tag_or_id, angle, x, y)
  • (x, y) 为中心旋转指定 ID 或标签的图形项 angle 度。
  • 获取图形的边界框

  • canvas.bbox(tag_or_id)
  • 返回指定 ID 或标签的图形项的边界框 (x1, y1, x2, y2)
  • 将图形提升到画布最上层

  • canvas.tag_raise(tag_or_id)
  • 将图形降低到画布最下层

  • canvas.tag_lower(tag_or_id)
  • 获取画布上所有的图形的id列表

  • canvas.find_all()
  • 根据标签或 ID 查找图形

  • canvas.find_withtag(tag_or_id)
  • 更新画布

  • canvas.update()
  • 强制更新画布显示,处理所有挂起的事件和界面更新。
  • 设置画布滚动区域

  • canvas.configure(scrollregion=(x1, y1, x2, y2))
  • 坐标说明

  • x1: 左边的左右
  • x2: 左边的上下
  • y1: 右边的左右
  • y2: 右边的上下
  • Canvas组件示例

    1.创建一个画布,显示画布边框

    import tkinter as tk
    
    root = tk.Tk()
    root.title("画布")
    root.geometry("300x200")
    
    # 创建画布
    canvas = tk.Canvas(root, width=280, height=180, bg="white", borderwidth=2, relief="solid")
    canvas.pack_propagate(False)
    canvas.pack()
    
    root.mainloop()

    2. 绘制图形

    import tkinter as tk
    
    root = tk.Tk()
    root.title("画布")
    root.geometry("320x220")
    
    canvas = tk.Canvas(root, width=300, height=200, bg="white", borderwidth=2, relief="solid")
    
    # 绘制直线 x1,左边的左右 x2:左边上下,y1:右边的左右  y2:右边上下
    canvas.create_line(10, 10, 290, 10, fill="blue", width=2)
    # 绘制矩形 x1,左边的左右 x2:左边上下,y1:右边的左右  y2:右边上下
    canvas.create_rectangle(10, 20, 290, 50, outline="black", fill="red")
    # 绘制椭圆形 x1,左边的左右 x2:左边上下,y1:右边的左右  y2:右边上下
    canvas.create_oval(10, 60, 290, 100, outline="green", fill="yellow")
    # 绘制文本 x:水平,y:垂直
    canvas.create_text(100, 120, text="Hello, Tkinter!", font=("Arial", 16))
    
    canvas.pack()
    
    root.mainloop()
    

    3. 绘制图像,图片不变形百分比缩放

    import tkinter as tk
    from PIL import Image, ImageTk
    
    def resize_image(image, max_width, max_height):
        # 获取图像的原始尺寸
        original_width, original_height = image.size
    
        # 计算调整后的宽度和高度
        ratio = min(max_width / original_width, max_height / original_height)
        new_width = int(original_width * ratio)
        new_height = int(original_height * ratio)
    
        # 调整图像大小
        return image.resize((new_width, new_height), Image.LANCZOS)
    
    root = tk.Tk()
    root.title("画布")
    root.geometry("320x220")
    
    # 创建画布
    canvas = tk.Canvas(root, width=300, height=200, bg="white", borderwidth=2, relief="solid")
    canvas.pack()
    
    # 调整图像大小,百分比缩放
    new_img_width = 100  # 新的宽度
    new_img_height = 100  # 新的高度
    # 加载原始图片
    original_image = Image.open("static/background/a.jpg")
    
    # 调整图片大小以适应画布
    resized_image = resize_image(original_image, new_img_width, new_img_height)
    photo = ImageTk.PhotoImage(resized_image)
    
    # 在 Canvas 上绘制图像
    canvas.create_image(150, 100, image=photo)
    
    root.mainloop()
    


    PhotoImage加载图片组件

    PhotoImage组件常用方法

    创建 PhotoImage 实例

  • PhotoImage(master=None, file=None, data=None)
  • master: 指定父组件。
  • file: 指定图像文件的路径。
  • data: 指定图像数据的字符串,例如Base64。
  • 创建 PhotoImage 实例的副本

  • copy()
  • 将图像数据插入到 PhotoImage 实例的指定位置

  • put(data, to=(x, y))
  • data: 要插入的图像数据。
  • to: 指定插入的起始坐标 (x, y)。
  • PhotoImage 实例保存为文件

  • write(filename, format=None)
  • filename: 文件名。
  • format: 可选的,指定保存图像的格式(例如 "png")。
  • 获取图像的高度

  • height()
  • 获取图像的宽度

  • width
  • PhotoImage组件示例

    1. 显示图片,图片大小不变

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.title("PhotoImage 示例")
    root.geometry("300x200")
    
    # 加载图像
    image = tk.PhotoImage(file="static/background/a.png")
    
    # 创建标签并显示图像
    label = tk.Label(root, image=image)
    label.pack()
    
    # 启动主事件循环
    root.mainloop()
    

    2. 在Label显示图片,调整图片大小

    from tkinter import Tk, Label
    from PIL import Image, ImageTk
    
    # 创建主窗口
    root = Tk()
    root.title("调整图像大小")
    root.geometry("300x200")
    
    # 使用 Pillow 加载图像
    original_image = Image.open("static/background/a.png")
    
    # 调整图像大小
    resized_image = original_image.resize((200, 200))  # 新尺寸为200x200像素
    
    # 将调整大小后的图像转换为 PhotoImage
    photo_image = ImageTk.PhotoImage(resized_image)
    
    # 创建标签并显示图像
    label = Label(root, image=photo_image)
    label.pack()
    
    # 启动主事件循环
    root.mainloop()
    


    PanedWindow可动态调整大小的窗口组件

    什么是PanedWindow

    PanedWindow是一个容器小部件,用于创建具有可调整分隔条的窗口布局。它允许你将窗口分成多个面板,并允许用户通过拖动分隔条来调整其子部件的大小。这种布局非常适合需要在多个区域间动态调整空间的应用场景。

    PanedWindow组件常用属性

    基本属性

  • orient: 指定 PanedWindow 中子部件的排列方向。tk.HORIZONTAL 表示水平排列,tk.VERTICAL 表示垂直排列。
  • sashwidth: 控制分隔线的宽度,默认值2像素。
  • sashpad: 控制分隔线与相邻子部件之间的间距,默认值0像素
  • sashrelief: 设置分隔线的外观样式。可能的值包括:tk.RAISED(默认), tk.SUNKEN, tk.FLAT, tk.RIDGE, tk.SOLID, tk.GROOVE。
  • handlesize: 控制分隔线手柄的大小,以像素为单位。默认值8像素。
  • handlepad: 控制手柄与分隔线之间的间距。默认值8像素
  • showhandle: 指示是否在分隔线的中间显示一个手柄。如果设置为 True,分隔线中间会显示一个小方块手柄,便于用户拖动。默认False
  • opaqueresize: 控制当用户拖动分隔线时,是否实时更新子部件的大小。如果设置为 True,则拖动时子部件大小会立即更新;如果设置为 False,则拖动时会显示一个轮廓,释放鼠标后才更新子部件大小。默认True。
  • 颜色和视觉属性

  • background / bg: 设置 PanedWindow 的背景颜色。
  • borderwidth / bd: 控制 PanedWindow 的边框宽度。默认0
  • relief: 设置边框的样式。可能的值包括:tk.FLAT(默认), tk.RAISED, tk.SUNKEN, tk.GROOVE, tk.RIDGE, tk.SOLID。
  • 布局和几何管理属性

  • height: 设置 PanedWindow 的初始高度,以像素为单位。
  • width: 设置 PanedWindow 的初始宽度,以像素为单位。
  • cursor: 设置鼠标在 PanedWindow 上方时的光标样式,例如 'arrow', 'circle', 'cross' 等。
  • 其他属性

  • takefocus: 指示 PanedWindow 是否可以通过Tab键接受键盘焦点。默认True
  • name: 设置小部件的内部名称,通常用于调试目的。
  • class_: 指定 PanedWindow 的窗口类名,默认是 PanedWindow,可以在窗口管理器中用于窗口配置。
  • PanedWindow组件常用方法

  • config(self, **options) / configure(self, **options): 配置或更新 PanedWindow 的属性。可以设置背景颜色、方向、分隔线宽度、是否允许调整大小等。
  • add(self, child, **options): 将一个子部件(如 Frame 或 Label 等)添加到 PanedWindow 中。options 可以设置子部件的大小比例、填充方式等。
  • remove(self, child): 从 PanedWindow 中移除一个子部件。
  • forget(self, child): 与 remove 方法类似,忘记一个子部件,即从 PanedWindow 中移除它。
  • paneconfig(self, pane, **options): 配置或更新一个已存在的子部件的属性。pane 是子部件,options 可以设置该子部件的大小、最小尺寸等。
  • panecget(self, pane, option): 获取一个子部件的特定属性的值。pane 是子部件,option 是要获取的属性名称。
  • panes(self): 返回 PanedWindow 中所有子部件的列表。
  • sashpos(self, index, newpos=None): 获取或设置分隔线的位置。index 是分隔线的索引(从0开始),newpos 是可选的参数,用于设置新的位置(以像素为单位)。
  • pack(self, **options): 使用 pack 管理器来放置 PanedWindow。
  • grid(self, **options): 使用 grid 管理器来放置 PanedWindow。
  • place(self, **options): 使用 place 管理器来放置 PanedWindow。
  • bind(self, sequence=None, func=None, add=None): 绑定一个事件处理函数到PanedWindow。
  • unbind(self, sequence, funcid=None): 解除绑定的事件处理函数。
  • PanedWindow组件示例

    1. 创建一个PanedWindow

    import tkinter as tk
    
    root = tk.Tk()
    root.title("PanedWindow Example")
    root.geometry("300x200")
    
    # 创建一个 PanedWindow,设置为水平分隔
    pw = tk.PanedWindow(root, orient=tk.HORIZONTAL)
    pw.pack(fill=tk.BOTH, expand=True)
    
    # 添加两个子部件
    left = tk.Frame(pw, bg='lightblue', width=150, height=200)
    pw.add(left)
    
    right = tk.Frame(pw, bg='lightgreen', width=150, height=200)
    pw.add(right)
    
    root.mainloop()
    

    2. 设置最小缩小尺寸

    pw.add(left, minsize=100) # 设置最小宽度为100像素

    3. 禁止拖动

    import tkinter as tk
    
    root = tk.Tk()
    root.title("PanedWindow 不能拖动大小")
    root.geometry("300x200")
    
    # 创建一个 PanedWindow,设置为水平分隔
    pw = tk.PanedWindow(root, orient=tk.HORIZONTAL)
    pw.pack(fill=tk.BOTH, expand=True)
    
    # 添加两个子部件
    left = tk.Frame(pw, bg='lightblue', width=100, height=200)
    pw.add(left, minsize=100)  # 两个子部件的和占满整个长度,来达到禁用拖动的目的
    
    right = tk.Frame(pw, bg='lightgreen', width=150, height=200)
    pw.add(right, minsize=200)  # 两个子部件的和占满整个长度,来达到禁用拖动的目的
    
    root.mainloop()
    

    4. 嵌套PanedWindow,类似网页的左侧菜单栏,上下导航栏

    import tkinter as tk
    from tkinter import PanedWindow
    
    root = tk.Tk()
    root.title("Vertical PanedWindow Example")
    root.geometry("300x200")
    
    # 创建一个垂直的 PanedWindow
    vertical_paned_window = PanedWindow(root, orient=tk.VERTICAL)
    vertical_paned_window.pack(fill=tk.BOTH, expand=True)
    
    # 添加第一个 Label 到垂直的 PanedWindow
    top_label = tk.Label(vertical_paned_window, text="Top Pane", bg="lightcoral")
    vertical_paned_window.add(top_label)
    
    # 嵌套一个水平的 PanedWindow 到垂直的 PanedWindow 中
    horizontal_paned_window = PanedWindow(vertical_paned_window, orient=tk.HORIZONTAL)
    vertical_paned_window.add(horizontal_paned_window)
    
    # 向嵌套的水平 PanedWindow 添加两个 Label
    left_label = tk.Label(horizontal_paned_window, text="Left Pane", bg="lightblue")
    horizontal_paned_window.add(left_label)
    
    right_label = tk.Label(horizontal_paned_window, text="Right Pane", bg="lightgreen")
    horizontal_paned_window.add(right_label)
    
    # 添加第三个 Label 到垂直的 PanedWindow
    bottom_label = tk.Label(vertical_paned_window, text="Bottom Pane", bg="lightgoldenrodyellow")
    vertical_paned_window.add(bottom_label)
    
    root.mainloop()
    


    Notebook选项卡组件

    Notebook组件常用属性

    Notebook属性

  • width 和 height: 指定 Notebook 的宽度和高度。可以是像素值或与其他窗口组件大小相对应的值。默认根据内容自动调整。
  • padding: 整数或字符串 (如 10 或 "10 5")。指定 Notebook内部内容的填充(padding)。可以是一个值(四周填充相同大小)或用空格分隔的多个值(指定各个方向的填充)。默认:0。
  • takefocus:
  • style: 指定 Notebook 的样式名称,以使用 ttk.Style 中定义的样式。
  • cursor: 指定鼠标指针悬停在 Notebook 上时的光标形状。
  • state: 指定 Notebook 的状态。'normal' 表示可用,'disabled' 表示不可用。
  • class: 用于指定窗口部件的类名,这通常用于样式和主题设置。
  • tabs:  一个包含所有当前选项卡的标识符的列表,可以通过 notebook.tabs() 方法获取。
  • 选项卡的属性:每个 Notebook 中的选项卡(Tab)也有自己的一些属性,这些属性可以在创建选项卡时设置或之后通过 tab() 方法配置。

  • text: 选项卡上显示的文本。默认无文本。
  • image: 选项卡上显示的图像。可以与 text 属性结合使用。默认None。
  • compound: 指定如何将 text 和 image 组合在一起。选项包括 'none', 'text', 'image', 'center', 'left', 'right', 'top', 'bottom'。
  • underline: 指定要下划线的字符索引(从0开始)。有助于访问键盘快捷键。默认 -1(无下划线)
  • state: 选项卡的状态。'normal' 表示可用,'disabled' 表示不可用,'hidden' 表示隐藏(但未删除)。
  • sticky: 指定选项卡的内容如何在选项卡内对齐。选项包括 'n', 's', 'e', 'w' 和它们的组合。 默认: 'nswe'(填满整个区域)。
  • Notebook组件常用方法

  • notebook = ttk.Notebook(parent, **options):初始化选项卡容器。parent: 父级容器组件。**options: 可选参数,如 width、height、padding 等。
  • add(child):添加一个选项卡片。child:选项卡容器中放的组件
  • forget(tab_id): 移除一个选项卡片。tab_id:选项卡的标识符,可以是选项卡的索引(从0开始)或选项卡的窗口对象。
  • tab_id = event.widget.select():获取选项卡标识符。
  • hide(tab_id): 隐藏一个选项卡(选项卡不会被销毁)。
  • select(tab_id=None): 选择并切换到指定选项卡。tab_id: 要选择的选项卡标识符。如果没有提供,将返回当前选项卡的标识符。
  • tab(tab_id, option=None, **kw): 配置或查询选项卡的属性。option: 要查询的选项(如 'text')。如果未提供,则返回所有选项。**kw: 要设置的选项。
  • tabs(): 返回所有选项卡的标识符。
  • index(tab_id): 返回给定选项卡的索引。
  • enable_traversal(): 启用键盘导航(使用 Ctrl+Tab 和 Ctrl+Shift+Tab 切换选项卡)。
  • ttk.Style().configure('TNotebook', **options):更改Notebook的外观。
  • ttk.Style().configure('TNotebook.Tab', **options):更改选项卡的外观。
  • bind("<<NotebookTabChanged>>", callback):绑定事件,当用户更改选项卡时触发。
  • Notebook组件示例

    1. 创建一个选项卡

    import tkinter as tk
    from tkinter import ttk
    
    
    def on_tab_change(event):
        tab_id = event.widget.select()
        print("Selected tab:", notebook.index(tab_id))
    
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Notebook 选项卡")
    root.geometry("300x200")
    
    # 创建Notebook组件
    notebook = ttk.Notebook(root)
    
    # 创建两个Frame,作为两个选项卡的内容
    frame1 = ttk.Frame(notebook, width=300, height=200)
    frame2 = ttk.Frame(notebook, width=300, height=200)
    
    label1 = tk.Label(frame1, text="选项卡1", bg="lightblue")
    label1.pack(fill=tk.BOTH, expand=True)
    label2 = tk.Label(frame2, text="选项卡2", bg="lightgreen")
    label2.pack(fill=tk.BOTH, expand=True)
    
    # 向Notebook添加选项卡
    notebook.add(frame1, text="Tab 1")
    notebook.add(frame2, text="Tab 2")
    
    # 布局Notebook
    notebook.pack(expand=True, fill=tk.BOTH)
    
    # 当用户更改选项卡时触发
    notebook.bind("<<NotebookTabChanged>>", on_tab_change)
    
    # 运行主事件循环
    root.mainloop()
    


    2. 添加和删除选项卡

    import tkinter as tk
    from tkinter import ttk
    
    def add_tab():
        frame = ttk.Frame(notebook, width=300, height=200)
        notebook.add(frame, text=f"Tab {notebook.index('end') + 1}")
    
    def remove_tab():
        if notebook.tabs():
            notebook.forget(notebook.select())
    
    # 创建主窗口
    root = tk.Tk()
    root.title("Add and Remove Tabs")
    
    # 创建Notebook组件
    notebook = ttk.Notebook(root)
    notebook.pack(expand=True, fill='both')
    
    # 添加初始选项卡
    frame1 = ttk.Frame(notebook, width=300, height=200)
    notebook.add(frame1, text="Tab 1")
    
    # 添加按钮来动态添加和删除选项卡
    button_frame = tk.Frame(root)
    button_frame.pack(fill='x')
    add_button = tk.Button(button_frame, text="Add Tab", command=add_tab)
    add_button.pack(side='left')
    remove_button = tk.Button(button_frame, text="Remove Tab", command=remove_tab)
    remove_button.pack(side='left')
    
    # 运行主事件循环
    root.mainloop()
    

    Radiobutton单选框组件

    Radiobutton组件常用属性

  • activebackground: 鼠标光标悬停在按钮上时的背景颜色。
  • activeforeground: 鼠标光标悬停在按钮上时的前景(文本)颜色。
  • anchor: 指定按钮文本的对齐方式。选项包括 n, ne, e, se, s, sw, w, nw, 和 center。
  • bg 或 background: 按钮的背景颜色。
  • bitmap: 按钮上显示的位图图像。
  • borderwidth 或 bd: 按钮边框的宽度,默认值为 2。
  • command: 当单选按钮被选中时调用的回调函数。
  • cursor: 鼠标悬停在按钮上时显示的光标类型。
  • disabledforeground: 按钮被禁用时的前景(文本)颜色。
  • fg 或 foreground: 按钮文本的前景颜色。
  • font: 按钮文本使用的字体。
  • height: 按钮的高度(以文本行数或像素为单位)。
  • highlightbackground: 按钮未被聚焦时的高亮背景颜色。
  • highlightcolor: 按钮被聚焦时的高亮背景颜色。
  • highlightthickness: 按钮高亮边框的厚度。
  • image: 显示在按钮上的图像对象。它可以是 PhotoImage 或 BitmapImage 对象。
  • indicatoron: 如果设置为 0,则单选按钮显示为按钮形式而不是传统的单选点形式。默认值为 1(显示为单选点)。
  • justify: 当文本超过一行时,指定文本的对齐方式。选项包括 LEFT, CENTER, 和 RIGHT。
  • padx: 按钮文本与按钮边框之间的水平填充(以像素为单位)。
  • pady: 按钮文本与按钮边框之间的垂直填充(以像素为单位)。
  • relief: 按钮边框的样式。选项包括 FLAT, SUNKEN, RAISED, GROOVE, 和 RIDGE。
  • selectcolor: 单选按钮被选中时的标记颜色。
  • selectimage: 按钮被选中时显示的图像(覆盖 image 属性)。
  • state: 按钮的状态。可以是 NORMAL(默认),ACTIVE 或 DISABLED。
  • takefocus: 控制按钮是否接受键盘焦点。可以是 0(不接受),1(接受),或空字符串(默认行为)。
  • text: 按钮上显示的文本。
  • textvariable: 绑定到按钮文本的变量。如果该变量的值改变,按钮文本也会自动更新。
  • underline: 指定按钮文本中被下划线的字符的索引位置(从 0 开始)。默认情况下,没有字符有下划线。
  • value: 单选按钮被选中时关联变量(variable)的值。
  • variable: 一个 tkinter 变量对象(例如 IntVar 或 StringVar),用于管理多个单选按钮的选择。每个单选按钮的 variable 属性相同,value 属性不同。
  • width: 按钮的宽度(以字符数或像素为单位)。
  • wraplength: 如果文本长于指定的宽度,则文本将在此宽度处换行。
  • Radiobutton组件常用方法

    Radiobutton组件示例

    1. 基本使用示例

    import tkinter as tk
    
    def on_select():
        print(f"Selected option: {var.get()}")
    
    root = tk.Tk()
    root.geometry("300x200")
    
    # 创建一个 StringVar 用来表示多个单选按钮是一组(同组中的选择互斥)
    var = tk.StringVar(value="1")
    
    # 创建单选按钮,并设置属性
    rb1 = tk.Radiobutton(
        root,
        text="男",
        variable=var,
        value="1",  # value的值和 variable里value的值相同,表示默认选中
        command=on_select,
        font=("Arial", 12),
        state=tk.DISABLED
    )
    
    rb2 = tk.Radiobutton(
        root,
        text="女",
        variable=var,
        value="2",
        command=on_select,
        font=("Arial", 12),
    )
    
    rb1.pack(side=tk.LEFT, padx=10, pady=5)
    rb2.pack(side=tk.LEFT, padx=10, pady=5)
    
    root.mainloop()
    


    Checkbutton复选框组件

    Checkbutton组件常用属性

  • text: 复选按钮上显示的文本。
  • variable: 绑定到复选按钮的 tkinter 变量对象(如 IntVar, StringVar, BooleanVar 等)。复选按钮的状态变化时,这个变量的值会自动更新。
  • onvalue: 当复选按钮被选中时,variable 变量的值。
  • offvalue: 当复选按钮未被选中时,variable 变量的值。
  • command: 当复选按钮的状态改变时要调用的函数。
  • state: 按钮的状态(如 NORMAL, DISABLED, ACTIVE)。
  • font: 文本的字体。
  • fg (或 foreground): 文本的前景色。
  • bg (或 background): 背景颜色。
  • selectcolor: 复选按钮方框选中时的背景颜色。
  • anchor: 文本在复选按钮区域内的对齐方式(如 E, W, N, S)。
  • justify: 多行文本的对齐方式(LEFT, CENTER, RIGHT)。
  • padx 和 pady: 内边距(水平和垂直)。
  • relief: 边框样式(如 RAISED, SUNKEN, FLAT, RIDGE, GROOVE, SOLID)。
  • Checkbutton组件常用方法

  • select(): 将复选按钮设置为选中状态。
  • deselect(): 将复选按钮设置为未选中状态。
  • toggle(): 切换复选按钮的状态(从选中到未选中或反之)。
  • invoke(): 程序性地触发复选按钮的命令。它会执行与复选按钮关联的 command 回调。
  • config() 或 configure(): 更新或获取复选按钮的配置选项。
  • cget(): 获取指定配置选项的值。
  • Checkbutton组件示例

    获取Checkbutton选中的值

    import tkinter as tk
    
    # 创建主窗口
    root = tk.Tk()
    root.geometry('300x200')
    
    
    # 回调函数:打印选中的 Checkbutton 值
    def get_selected_values():
        selected_options = []
        if var1.get() == 1:
            selected_options.append(checkbutton1.cget("text"))
        if var2.get() == 1:
            selected_options.append(checkbutton2.cget("text"))
        if var3.get() == 1:
            selected_options.append(checkbutton3.cget("text"))
    
        print("选中:", selected_options)
    
    
    # 创建变量来追踪每个 Checkbutton 的状态
    var1 = tk.IntVar()
    var2 = tk.IntVar(value=1)  # 默认选中
    var3 = tk.IntVar()
    
    # 创建 Checkbutton
    checkbutton1 = tk.Checkbutton(root, text="苹果", variable=var1)
    checkbutton2 = tk.Checkbutton(root, text="橙子", variable=var2)
    checkbutton3 = tk.Checkbutton(root, text="西瓜", variable=var3)
    
    # 创建一个按钮来提交选择
    submit_button = tk.Button(root, text="提交", command=get_selected_values)
    
    # 使用 pack() 布局管理器来放置组件
    checkbutton1.pack()
    checkbutton2.pack()
    checkbutton3.pack()
    submit_button.pack()
    
    # 进入主循环
    root.mainloop()
    


    Scale滑动条组件

    Scale组件常用属性

  • from_: 设置滑动条的最小值。
  • to: 设置滑动条的最大值。
  • orient: 设置滑动条的方向,可以是 tk.HORIZONTAL 或 tk.VERTICAL。
  • length: 设置滑动条的长度(在垂直方向上为高度)。
  • width: 设置滑动条的宽度(在水平滑动条上为宽度)。
  • sliderlength: 设置滑块的长度(在水平滑动条上为高度)。
  • resolution: 设置滑动条的刻度分辨率。
  • tickinterval: 设置刻度线之间的间隔。
  • showvalue: 设置是否显示当前值。
  • variable: 绑定一个 tk.Variable 对象来显示和更新滑动条的值。
  • Scale组件常用方法

  • get(): 获取当前滑动条的值。
  • set(value): 设置滑动条的值。
  • invoke(): 启动滑动条的操作(通常用于菜单中的命令)。
  • configure(**kwargs): 配置或更新滑动条的属性。
  • Scale组件示例

    1. Scale使用示例

    import tkinter as tk
    
    def on_scale_change(value):
        print(f"Scale value: {value}")
    
    root = tk.Tk()
    root.geometry("300x200")
    
    scale = tk.Scale(root,
                     from_=0,  # 滑动条的最小值
                     to=100,  # 滑动条的最大值
                     orient=tk.HORIZONTAL,  # 滑动条水平方向
                     length=280,  # 滑动条的长度
                     width=20,  # 滑动条的宽度
                     sliderlength=50,  # 滑动块的长度
                     resolution=1,
                     tickinterval=10,  # 刻度线(滑动条下面的数字)的间隔,每隔10显示一个数字
                     showvalue=True  # 显示当前进度值(滑动条上面的数字)
                     )
    scale.pack()
    
    # 绑定滑动条值变化的事件
    scale.bind("<Motion>", lambda event: on_scale_change(scale.get()))
    
    root.mainloop()
    

    2. 动态获取进度数据

    import tkinter as tk
    
    def update_value():
        current_value = scale.get()
        print(f"当前进度: {current_value}")
        if current_value != 100:
            scale.set(current_value + 20)  # 加载进度值
            root.after(1000, update_value)  # 每1000毫秒(即1秒)调用一次update_value函数
    
    root = tk.Tk()
    root.geometry("300x200")
    
    scale = tk.Scale(root,
                     from_=0,  # 滑动条的最小值
                     to=100,  # 滑动条的最大值
                     orient=tk.HORIZONTAL,  # 滑动条水平方向
                     length=280,  # 滑动条的长度
                     width=3,  # 滑动条的宽度
                     sliderlength=10,  # 滑动块的长度
                     resolution=1,
                     showvalue=True,  # 显示当前进度值(滑动条上面的数字)
                     )
    scale.pack()
    
    # 启动定时器以每秒更新一次值
    root.after(1000, update_value)  # 1000毫秒后调用update_value函数
    
    root.mainloop()
    


    Spinbox数值选择器组件

    Spinbox是tkinter提供的一种控件,用于让用户从一系列预定义的选项中选择一个值。它通常表现为一个带有上下箭头的文本框,用户可以通过点击箭头来增加或减少当前值,也可以直接输入一个值。

    Spinbox组件常用方法

    未完待续。。。

    作者:又逢乱世

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python Tkinter GUI框架深度解析

    发表回复