Python GUI 编程
Python GUI 编程 (tkinter)
Section titled “Python GUI 编程 (tkinter)”Python 提供了多种用于创建图形用户界面(GUI, Graphical User Interface)的库。其中一些流行的选项包括:
tkinter: (在 Python 2 中曾称为Tkinter)是 Python 标准内置的 Tcl/Tk GUI 工具包接口。它是跨平台的,并且相对容易上手。本章节将重点介绍tkinter。PyQt/PySide: 是强大的 Qt 框架的绑定。提供了广泛的现代窗口部件和功能。常用于复杂的桌面应用程序。Kivy: 一个用于开发多点触控应用的开源库。适用于现代 UI、游戏和移动开发。wxPython: 是 wxWidgets C++ 库的绑定。另一个成熟的跨平台工具包。- Web 框架(带包装器):使用 Flask/Django 等框架配合
PyWebView或类似Electron的包装器来使用 Web 技术创建桌面应用。
tkinter 编程
Section titled “tkinter 编程”tkinter 提供了一种直接使用 Python 构建 GUI 应用程序的简单方法。它封装了 Tcl/Tk 工具包,将其组件作为 Python 类提供。
创建 tkinter 应用的基本步骤:
- 导入
tkinter模块(通常导入为tk)。 - 创建主应用程序窗口(
tk.Tk的实例)。 - 向主窗口或其他容器窗口部件(如 Frame)添加窗口部件(按钮、标签、输入框等)。
- 使用几何管理器(
pack、grid、place)配置窗口部件属性和布局。 - 定义事件处理程序(用户点击按钮等时调用的函数)。
- 启动
tkinter主事件循环(mainloop()),使窗口具有交互性并响应用户操作。
基本示例:一个简单的窗口
Section titled “基本示例:一个简单的窗口”#!/usr/bin/env python3
import tkinter as tk
# 1. Create the main window# 1. 创建主窗口root = tk.Tk()root.title("Simple Tkinter App") # Set window title# 设置窗口标题root.geometry("300x150") # Set initial window size (width x height)# 设置初始窗口大小(宽度 x 高度)
# 2. Add widgets (example: a label)# 2. 添加窗口部件(示例:一个标签)my_label = tk.Label(root, text="Hello, Tkinter!")my_label.pack(pady=20) # Use pack geometry manager with padding# 使用 pack 几何管理器,并添加垂直内边距
# 3. Add a button with an action# 3. 添加一个带动作的按钮def on_button_click(): print("Button clicked!") my_label.config(text="Button was clicked!")
my_button = tk.Button(root, text="Click Me", command=on_button_click)my_button.pack()
# 4. Start the main event loop# 4. 启动主事件循环root.mainloop()
# Code after mainloop() executes only after the window is closed.# mainloop() 之后的代码只有在窗口关闭后才会执行。运行此脚本将创建一个标题为 “Simple Tkinter App” 的小窗口,其中包含文本 “Hello, Tkinter!” 和一个标有 “Click Me” 的按钮。点击按钮会在控制台打印一条消息,并更改标签的文本。
tkinter 窗口部件 (Widgets)
Section titled “tkinter 窗口部件 (Widgets)”窗口部件是 tkinter GUI 的构建块(按钮、文本框、标签等)。每个窗口部件都由一个类表示。
常用窗口部件:
| 窗口部件类 / 模块 | 描述 |
|---|---|
Tk | 应用程序的主(根)窗口。 |
Toplevel | 创建额外的独立窗口。 |
Frame | 一个容器窗口部件,用于分组和组织其他窗口部件。 |
Label | 显示静态文本或图像。 |
Button | 一个可点击的按钮,可以触发函数调用(command)。 |
Entry | 单行文本输入字段。 |
Text | 多行文本输入和显示区域。 |
Checkbutton | 复选框,允许选择/取消选择。 |
Radiobutton | 允许从一组选项中选择一个(通过共享变量链接)。 |
Listbox | 显示项目列表,用户可以从中选择。 |
Scrollbar | 为 Listbox、Text、Canvas 等窗口部件添加滚动功能。 |
Menu | 创建菜单栏和上下文菜单。 |
Scale | 一个滑块窗口部件,用于选择范围内的值。 |
Canvas | 一个多功能窗口部件,用于绘制形状、线条、文本、图像以及嵌入其他窗口部件。 |
Spinbox | 一个带上下箭头的 Entry 窗口部件,用于从值范围中选择。 |
LabelFrame | 带可见边框和文本标签的 Frame。 |
PanedWindow | 管理可由用户调整大小的窗格的容器。 |
Message | 类似于 Label,但设计用于多行文本消息。 |
messagebox (模块) | tkinter.messagebox 提供用于标准对话框(信息、警告、错误、询问是/否等)的函数。 |
窗口部件配置选项
Section titled “窗口部件配置选项”窗口部件有许多选项(属性)控制其外观和行为。这些选项可以在创建时设置,也可以稍后使用 config() 或 configure() 方法(或类似字典的访问方式 widget['option'] = value)修改。
常用选项包括:
text: 窗口部件上显示的文本(Label、Button 等)。textvariable: 一个链接到窗口部件文本/值的tkinter变量(StringVar、IntVar等)。变量的更改会更新窗口部件,反之亦然(对于 Entry、Checkbutton、Radiobutton、Scale)。command: 窗口部件激活时(例如,Button 点击)调用的函数。width、height: 窗口部件的大小(单位取决于窗口部件,通常是文本单位或像素)。bg(或background)、fg(或foreground):背景色和文本/前景色。font: 指定字体(例如,('Arial', 12, 'bold'))。relief: 边框样式(flat平坦、raised凸起、sunken凹陷、groove凹槽、ridge脊)。borderwidth(或bd):边框宽度。state: 窗口部件状态(normal正常、disabled禁用、readonly只读)。anchor: 内容在窗口部件空间内的位置(例如,tk.N北、tk.S南、tk.E东、tk.W西、tk.CENTER居中)。padx、pady: 内部填充(内容与边框之间的空间)。image: 显示图像(需要PhotoImage或BitmapImage对象)。
使用选项的示例:
import tkinter as tk
root = tk.Tk()root.title("Widget Options")
# Label with specific font and color# 带有特定字体和颜色的标签label = tk.Label( root, text="Styled Label", font=("Helvetica", 16, "italic"), fg="blue", bg="lightgrey", padx=10, pady=10, relief=tk.RAISED, borderwidth=2)label.pack(pady=10)
# Button initially disabled# 最初禁用的按钮button = tk.Button(root, text="Disabled Button", state=tk.DISABLED)button.pack(pady=5)
# Function to enable the button# 用于启用按钮的函数def enable_button(): button.config(state=tk.NORMAL) button['text'] = "Enabled!"
enabler_button = tk.Button(root, text="Enable Other Button", command=enable_button)enabler_button.pack(pady=5)
root.mainloop()几何管理器控制窗口部件在其父容器内的位置和大小。tkinter 提供了三种主要的管理器:
pack(): 按块组织窗口部件。窗口部件沿容器剩余空间的边缘(top上、bottom下、left左、right右)依次打包。对于基本布局很简单,但对于复杂设计可能会变得复杂。grid(): 将窗口部件排列成表格状的行和列网格。对位置和对齐提供更精确的控制。对于复杂布局非常灵活。place(): 允许使用绝对坐标 (x, y) 或容器内的相对位置/大小定位窗口部件。对于一般布局不太常用,因为它不太适应窗口大小调整或内容变化,但对于特定的定位需求很有用。
重要提示: 在同一个父容器内,不应混合使用 pack() 和 grid()。对于直接位于特定 Frame 或 Window 内的窗口部件,应始终使用其中一种。但是,可以在一个 Frame 内使用 pack,而在同一窗口内的另一个 Frame 内使用 grid。
pack() 示例:
Section titled “pack() 示例:”label1 = tk.Label(root, text="Top", bg="red")label1.pack(side=tk.TOP, fill=tk.X) # Fill horizontally# 水平填充
label2 = tk.Label(root, text="Left", bg="blue")label2.pack(side=tk.LEFT, fill=tk.Y) # Fill vertically# 垂直填充
label3 = tk.Label(root, text="Center", bg="green")label3.pack(expand=True, fill=tk.BOTH) # Expand to fill remaining space# 扩展填充剩余空间grid() 示例:
Section titled “grid() 示例:”entry1 = tk.Entry(root)entry1.grid(row=0, column=1, padx=5, pady=5)label1 = tk.Label(root, text="Label 1:")label1.grid(row=0, column=0, sticky=tk.E) # Align right# 右对齐
entry2 = tk.Entry(root)entry2.grid(row=1, column=1, padx=5, pady=5)label2 = tk.Label(root, text="Longer Label 2:")label2.grid(row=1, column=0, sticky=tk.E)
button = tk.Button(root, text="Submit")# Span across 2 columns, add padding, stick to bottom-right corner within cell# 跨越 2 列,添加内边距,在单元格内粘滞到底部右侧button.grid(row=2, column=0, columnspan=2, pady=10, sticky=tk.SE)place() 示例:
Section titled “place() 示例:”button1 = tk.Button(root, text="Absolute Position")button1.place(x=50, y=50)
button2 = tk.Button(root, text="Relative Position")# Place at 70% width, 70% height relative to parent size# 相对于父容器大小,放置在 70% 宽度,70% 高度处button2.place(relx=0.7, rely=0.7, anchor=tk.CENTER) # anchor center# 锚定中心GUI 响应用户交互(事件),例如按钮点击、按键、鼠标移动。tkinter 使用回调和事件绑定。
command选项:许多窗口部件(如 Button、Checkbutton、Radiobutton)有一个command选项,用于指定窗口部件被激活时要调用的函数。bind()方法:提供了一种更通用的方式,将 Python 函数(事件处理程序)绑定到任何窗口部件上的特定事件(例如<Button-1>用于左键单击,<KeyPress>用于按键,<Enter>用于鼠标进入窗口部件区域)。
使用 bind() 的示例:
import tkinter as tk
def handle_click(event): # 'event' object contains details like coordinates (event.x, event.y) # 'event' 对象包含坐标等详细信息 (event.x, event.y) print(f"Left mouse button clicked at ({event.x}, {event.y})")
def handle_keypress(event): print(f"Key pressed: '{event.char}' (Key code: {event.keycode})")
root = tk.Tk()root.geometry("300x200")
frame = tk.Frame(root, width=200, height=100, bg="lightblue")# Bind left mouse click event (<Button-1>) on the frame# 将左键单击事件 (<Button-1>) 绑定到 frame 上frame.bind("<Button-1>", handle_click)frame.pack(pady=20)
entry = tk.Entry(root)# Bind any key press event (<KeyPress>) on the entry widget# 将任意按键事件 (<KeyPress>) 绑定到 entry 窗口部件上entry.bind("<KeyPress>", handle_keypress)entry.pack(pady=10)entry.focus_set() # Give focus to entry so keypresses are captured# 将焦点设置到 entry,以便捕获按键
root.mainloop()进一步学习:
Section titled “进一步学习:”- Tkinter 文档:https://docs.python.org/3/library/tkinter.html
- Tkinter 教程资源(例如,TkDocs、ZetCode Tkinter)。
- 考虑探索
tkinter.ttk中的主题窗口部件,以获得更现代的外观和感觉。