使用tkinter Entry控件实现图像标注实时更新方案
实现方案
核心不需要按钮触发,直接监听输入框绑定的变量变化,数值合法时自动重绘标注线即可,具体逻辑:
- 用
StringVar的trace监听机制,绑定输入内容写入事件,内容变化时自动执行标注更新函数 - 每次更新标注前先删除上一次绘制的红线,避免画布上堆叠重复线条
- 增加输入合法性校验,输入为空、非数字、数值超出图像范围时不抛错,静默等待合法输入
- 直接用tkinter Canvas原生的画线接口绘制标注,不要混用matplotlib的subplot,避免组件冲突、刷新卡顿
修正后可直接运行的代码
import tkinter as tk from tkinter import StringVar, Tk from PIL import Image, ImageTk root = Tk() root.geometry("500x750") frame = tk.Frame(root, width=480, height=450) frame.place(x=2, y=287) canvas = tk.Canvas(frame, bg="gray80", bd=1, height=400, width=470) canvas.pack() v_line = None IMG_X_MIN = 25 IMG_X_MAX = 445 IMG_Y_MIN = 12 IMG_Y_MAX = 402 img = None def Create_Image(): global img, canv_img Img = Image.open('.\\image.png') # 旧版本PIL把Resampling.LANCZOS换成Image.ANTIALIAS img = ImageTk.PhotoImage(Img.resize((420, 390), Image.Resampling.LANCZOS)) canv_img = canvas.create_image(235, 207, image=img, anchor=tk.CENTER) def update_annotate(*args): global v_line if v_line: canvas.delete(v_line) input_val = var.get().strip() if not input_val: return try: num = int(input_val) # 按实际输入值的范围修改坐标映射逻辑 if 0 <= num <= 420: canvas_x = IMG_X_MIN + num v_line = canvas.create_line(canvas_x, IMG_Y_MIN, canvas_x, IMG_Y_MAX, fill="red", width=2) except ValueError: return var = StringVar() input_entry = tk.Entry(root, textvariable=var) input_entry.place(x=50, y=10) # 绑定输入变化监听,写入即触发更新 var.trace_add("write", update_annotate) Create_Image() root.mainloop()
补充说明
- 旧版本tkinter(Python3.7及更早)将
var.trace_add("write", update_annotate)替换为var.trace("w", update_annotate)即可正常运行 - 代码中的坐标值是按照示例里resize后的420*390图像、锚点为中心的摆放位置计算的,如果图像尺寸、摆放位置变更,对应修改
IMG_X_MIN等常量和坐标映射逻辑就行 - 原代码里的matplotlib绘图逻辑可以完全删掉,原生Canvas画线性能更好,和tkinter适配没有兼容问题
内容的提问来源于stack exchange,提问作者user19333121
相关产品推荐
相关产品推荐

