tkinter
tkinter
是 Python 的标准库之一,不需要单独安装。只需要在代码中导入即可:
import tkinter as tk
from tkinter import messagebox
使用 tkinter
创建一个基本窗口非常简单:
# 创建主窗口
root = tk.Tk()
# 设置窗口标题
root.title("我的第一个 GUI 程序")
# 设置窗口大小
root.geometry("400x300")
# 进入主事件循环
root.mainloop()
可以使用 Label
小部件在窗口中显示文本:
label = tk.Label(root, text="Hello, Tkinter!")
label.pack()
可以使用 Button
小部件创建按钮,并指定按钮被点击时调用的函数:
def on_button_click():
messagebox.showinfo("信息", "按钮被点击了!")
button = tk.Button(root, text="点击我", command=on_button_click)
button.pack()
可以使用 Entry
小部件创建文本输入框:
entry = tk.Entry(root)
entry.pack()
def on_submit():
user_input = entry.get()
messagebox.showinfo("信息", f"你输入了:{user_input}")
submit_button = tk.Button(root, text="提交", command=on_submit)
submit_button.pack()
可以使用 Checkbutton
小部件创建复选框:
check_var = tk.IntVar()
checkbutton = tk.Checkbutton(root, text="同意条款", variable=check_var)
checkbutton.pack()
def on_check():
if check_var.get():
messagebox.showinfo("信息", "已同意条款")
else:
messagebox.showinfo("信息", "未同意条款")
check_button = tk.Button(root, text="检查复选框状态", command=on_check)
check_button.pack()
可以使用 Radiobutton
小部件创建单选按钮:
radio_var = tk.StringVar()
radiobutton1 = tk.Radiobutton(root, text="选项1", variable=radio_var, value="1")
radiobutton2 = tk.Radiobutton(root, text="选项2", variable=radio_var, value="2")
radiobutton1.pack()
radiobutton2.pack()
def on_radio_select():
selected_option = radio_var.get()
messagebox.showinfo("信息", f"你选择了:{selected_option}")
select_button = tk.Button(root, text="检查单选按钮状态", command=on_radio_select)
select_button.pack()
tkinter
提供了三种布局管理器:pack
、grid
和 place
。
pack
是最简单的布局管理器,它根据小部件的顺序将其添加到窗口中:
label1 = tk.Label(root, text="上")
label1.pack(side=tk.TOP)
label2 = tk.Label(root, text="左")
label2.pack(side=tk.LEFT)
label3 = tk.Label(root, text="右")
label3.pack(side=tk.RIGHT)
label4 = tk.Label(root, text="下")
label4.pack(side=tk.BOTTOM)
grid
是一个基于网格的布局管理器,可以更灵活地控制小部件的位置:
label1 = tk.Label(root, text="行0 列0")
label1.grid(row=0, column=0)
label2 = tk.Label(root, text="行0 列1")
label2.grid(row=0, column=1)
label3 = tk.Label(root, text="行1 列0")
label3.grid(row=1, column=0)
label4 = tk.Label(root, text="行1 列1")
label4.grid(row=1, column=1)
place
是一个绝对布局管理器,可以精确控制小部件的位置:
label1 = tk.Label(root, text="绝对位置")
label1.place(x=100, y=50)
import tkinter as tk
from tkinter import messagebox
def on_button_click():
messagebox.showinfo("信息", "按钮被点击了!")
def on_submit():
user_input = entry.get()
messagebox.showinfo("信息", f"你输入了:{user_input}")
def on_check():
if check_var.get():
messagebox.showinfo("信息", "已同意条款")
else:
messagebox.showinfo("信息", "未同意条款")
def on_radio_select():
selected_option = radio_var.get()
messagebox.showinfo("信息", f"你选择了:{selected_option}")
# 创建主窗口
root = tk.Tk()
root.title("我的第一个 GUI 程序")
root.geometry("400x300")
# 标签
label = tk.Label(root, text="Hello, Tkinter!")
label.pack()
# 按钮
button = tk.Button(root, text="点击我", command=on_button_click)
button.pack()
# 输入框
entry = tk.Entry(root)
entry.pack()
submit_button = tk.Button(root, text="提交", command=on_submit)
submit_button.pack()
# 复选框
check_var = tk.IntVar()
checkbutton = tk.Checkbutton(root, text="同意条款", variable=check_var)
checkbutton.pack()
check_button = tk.Button(root, text="检查复选框状态", command=on_check)
check_button.pack()
# 单选按钮
radio_var = tk.StringVar()
radiobutton1 = tk.Radiobutton(root, text="选项1", variable=radio_var, value="1")
radiobutton2 = tk.Radiobutton(root, text="选项2", variable=radio_var, value="2")
radiobutton1.pack()
radiobutton2.pack()
select_button = tk.Button(root, text="检查单选按钮状态", command=on_radio_select)
select_button.pack()
# 进入主事件循环
root.mainloop()
首先要补充tkinter
中 Canvas
这个非常强大的小部件:
Canvas
是一个绘图区域,可以在其中绘制线条、矩形、圆形、文本和图像等。Canvas
小部件非常适合创建需要自定义绘图的应用程序,如图表、游戏、图形编辑器等。
它既有一些内部函数可以直接调用,如绘制线条canvas.create_line
、绘制矩形canvas.create_rectangle
、绘制椭圆canvas.create_oval
、绘制多边形canvas.create_polygon
、绘制文本canvas.create_text
。也可以进行一些简单的事件处理,下面的示例代码中绑定了鼠标左键点击事件,并在点击的位置显示坐标。
进一步可以借助 PIL
(Python Imaging Library)库来加载并显示图像。需要安装 PIL
或 Pillow
库:
pip install pillow
上述基本功能的简单示例:
import tkinter as tk
from PIL import Image, ImageTk
def on_canvas_click(event):
x, y = event.x, event.y
canvas.create_text(x, y, text=f"({x}, {y})", font=("Arial", 12), fill="black")
root = tk.Tk()
root.title("Canvas 示例")
root.geometry("500x400")
canvas = tk.Canvas(root, width=500, height=400, bg="white")
canvas.pack()
# 绘制基本形状
canvas.create_line(50, 50, 200, 50, fill="blue", width=5)
canvas.create_rectangle(50, 100, 200, 200, outline="red", width=3)
canvas.create_oval(250, 100, 400, 200, outline="green", width=3)
canvas.create_polygon(250, 250, 300, 300, 350, 250, fill="yellow", outline="black")
canvas.create_text(250, 50, text="Hello, Canvas!", font=("Arial", 20), fill="purple")
# 加载并显示图像
image = Image.open("path/to/your/image.jpg")
photo = ImageTk.PhotoImage(image)
canvas.create_image(250, 200, image=photo)
# 绑定事件
canvas.bind("<Button-1>", on_canvas_click)
root.mainloop()
借助 matplotlib
库来实现简单的实时动画。需要安装 matplotlib
库:
pip install matplotlib
导入如下:
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.animation import FuncAnimation
import matplotlib.pyplot as plt
FigureCanvasTkAgg
功能概述 FigureCanvasTkAgg
是 matplotlib
和 tkinter
结合使用时的一个关键类。主要负责将 matplotlib
图形渲染到 tkinter
的 Canvas
上。具体来说,它将一个 matplotlib
的 Figure
对象嵌入到 tkinter
窗口中,使得可以在 tkinter
的应用程序中展示 matplotlib
图形,并且可以对图形进行交互(例如缩放、平移等)。
以下是一个完整的示例,演示如何在 tkinter
窗口中嵌入 matplotlib
图形:
import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
# 创建主窗口
root = tk.Tk()
root.title("嵌入 Matplotlib 图形")
root.geometry("800x600")
# 创建一个 Matplotlib 图形对象
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot(111)
ax.plot([0, 1, 2, 3, 4], [10, 1, 20, 15, 10])
# 将 Matplotlib 图形嵌入到 Tkinter 窗口中
canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
# 添加退出按钮
def on_exit():
root.quit()
root.destroy()
button = ttk.Button(master=root, text="退出", command=on_exit)
button.pack(side=tk.BOTTOM)
# 启动主事件循环
root.mainloop()
FuncAnimation
功能概述 FuncAnimation
是 matplotlib.animation
模块中的一个类,用于创建动画。它可以通过不断调用一个更新函数来生成动画效果,适用于在 matplotlib
图表上动态展示数据变化。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
# 创建一个图形对象和子图
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'b-', animated=True)
# 初始化函数,用于设置图表的初始状态
def init():
ax.set_xlim(0, 2 * np.pi)
ax.set_ylim(-1, 1)
return ln,
# 更新函数,用于更新图表上的数据
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
return ln,
# 创建动画
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2 * np.pi, 128),
init_func=init, blit=True)
# 显示动画
plt.show()
综上,通过FigureCanvasTkAgg
绑定fig
与canvas
,而fig
任你发挥,无论是上述的利用FuncAnimation
建立实时动画,还是利用matplotlib
实现其他更多样的功能。
除了上述的PIL
库,还用到了博大精深的opencv
,因为作者时间紧张,这里仅提供一个作者之前测试基本功能的简单demo,有着完善的备注作为参考,有兴趣的同学可以copy运行。
import os
import cv2
from tkinter import *
from PIL import Image, ImageTk
import time
# 创建一个新的文件夹
output_folder = "output_videos"
os.makedirs(output_folder, exist_ok=True)
# 指定视频文件路径
video_file_path = os.path.join(output_folder, "output.avi")
# 创建TKinter窗口或框架的实例
win = Tk()
# 设置窗口的大小
win.geometry("640x480")
# 创建标签以捕获视频帧
label = Label(win)
label.grid(row=0, column=0)
# 打开默认摄像头
cap = cv2.VideoCapture(1, cv2.CAP_DSHOW)
cap.isOpened()
# 设置摄像头的分辨率
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
cap.set(cv2.CAP_PROP_FPS, 30)
# 定义视频编解码器并创建 VideoWriter 对象
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
out = cv2.VideoWriter(video_file_path, fourcc, 30.0, (640, 480))
i = 0
fps = "0"
t1 = time.time()
# 显示帧
def show_frame():
global i
global t1
global fps
ret, frame = cap.read()
i += 1
if (time.time() - t1) > 1:
fps = i / (time.time() - t1)
fps = str(round(fps,2))
i = 0
t1 = time.time()
cv2.putText(frame, "FPS:"+fps, (20, 20), 1, 1.5, (255, 255, 255), 2)
if ret:
# 将帧写入视频文件
out.write(frame)
# 将帧从 BGR 转换为 RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 将帧转换为 ImageTk 格式
frame = ImageTk.PhotoImage(Image.fromarray(frame))
# 更新标签的图像
label.imgtk = frame
label.configure(image=frame)
# 20 毫秒后显示下一帧
label.after(20, show_frame)
# 关闭窗口时释放资源
def on_closing():
out.release()
cap.release()
cv2.destroyAllWindows()
win.destroy()
win.protocol("WM_DELETE_WINDOW", on_closing)
show_frame()
win.mainloop()