当前位置: 首页 > news >正文

在线测试来料公差


UI

上图 V1



上图 V2





 

V3




Code

import tkinter as tk
from tkinter import messagebox, scrolledtext
import socket
import threading
from datetime import datetime
import os
import logging
from PIL import Image, ImageTk
import subprocess# 定义文件夹路径
folder_path = r'c:\Log123'# 创建日志文件夹
if not os.path.exists(folder_path):os.makedirs(folder_path)# 设置日志记录
logging.basicConfig(filename=os.path.join(folder_path, 'log.log'), level=logging.INFO,format='%(asctime)s:%(levelname)s:%(message)s')class IndustrialApp:def __init__(self, root):self.root = rootself.root.title("Design_By_Tim")self.root.geometry("1200x700")self.root.configure(bg="#333333")# 图像加载相关变量self.img_index = 0self.current_img = None# 创建三列布局self.create_image_column()   # 左侧图像列self.create_control_column()  # 中间控制列self.create_status_column()   # 右侧状态列# 初始化网络连接self.client_socket = None self.standard_dimensions = {}self.standard_tolerances = {}self.update_standard_rectangle()  # 从输入框初始化标准数据# 启动图像更新self.img_update()def create_image_column(self):"""创建左侧图像列"""image_frame = tk.Frame(self.root, bg="#222222", width=400)image_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(10,5), pady=10)image_frame.pack_propagate(False)  # 固定宽度# 图像显示标签self.img_label = tk.Label(image_frame, bg="#222222")self.img_label.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)# 视觉打开按钮vision_button = tk.Button(image_frame, text="打开视觉系统", command=self.open_vision_system,font=("黑体", 18, "bold"), fg="#FFFFFF", bg="#006699",relief=tk.RAISED, borderwidth=3)vision_button.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)def create_control_column(self):"""创建中间控制列"""control_frame = tk.Frame(self.root, bg="#333333")control_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=10)# 工业风启动按钮self.start_button = tk.Button(control_frame, text="开始测量", command=self.send_command,font=("黑体", 16, "bold"), fg="#FFFFFF", bg="#006699",relief=tk.RAISED, borderwidth=3, width=8)self.start_button.pack(side=tk.TOP, fill=tk.X, anchor=tk.NW, padx=10, pady=10)# 绘图画布self.canvas = tk.Canvas(control_frame, bg="#444444", highlightthickness=0)self.canvas.pack(fill=tk.BOTH, expand=True)# 新增: 醒目的判断结果展示区域self.result_frame = tk.Frame(control_frame, bg="#333333", height=80)self.result_frame.pack(fill=tk.X, pady=(10, 0))# 初始状态为"等待测量"self.result_label = tk.Label(self.result_frame, text="等待测量...", font=("黑体", 24, "bold"), bg="#333333", fg="#FFFFFF")self.result_label.pack(expand=True, fill=tk.BOTH)# 详细结果标签self.detail_result_label = tk.Label(self.result_frame, text="", font=("黑体", 12), bg="#333333", fg="#FFFFFF")self.detail_result_label.pack(fill=tk.X, pady=(0, 5))def create_status_column(self):"""创建右侧状态列"""right_frame = tk.Frame(self.root, bg="#333333", width=300)right_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=(5,10), pady=10)right_frame.pack_propagate(False)  # 固定宽度# 标准矩形设置区settings_frame = tk.LabelFrame(right_frame, text="标准设置", font=("黑体", 12),bg="#333333", fg="#FFFFFF")settings_frame.pack(pady=10, fill=tk.X)# 尺寸输入框   315.021,131.784,315.085,132.322dimensions = [("上边 (mm):", "top", 315.021), ("右边 (mm):", "right", 131.784),("下边 (mm):", "bottom", 315.085), ("左边 (mm):", "left", 132.322)]self.entries = {}for i, (label, name, default_value) in enumerate(dimensions):tk.Label(settings_frame, text=label, bg="#333333", fg="#FFFFFF").grid(row=i, column=0, padx=5, pady=5)entry = tk.Entry(settings_frame, width=10)entry.grid(row=i, column=1, padx=5, pady=5)entry.insert(0, str(default_value))self.entries[name] = entry# 公差输入框tolerances = [("上边公差 (mm):", "top_tol", 0.1), ("右边公差 (mm):", "right_tol", 0.1),("下边公差 (mm):", "bottom_tol", 0.1), ("左边公差 (mm):", "left_tol", 0.1)]self.tolerance_entries = {}for i, (label, name, default_value) in enumerate(tolerances):tk.Label(settings_frame, text=label, bg="#333333", fg="#FFFFFF").grid(row=i, column=2, padx=5, pady=5)entry = tk.Entry(settings_frame, width=10)entry.grid(row=i, column=3, padx=5, pady=5)entry.insert(0, str(default_value))self.tolerance_entries[name] = entry# 更新按钮update_button = tk.Button(settings_frame, text="更新标准数据", command=self.update_standard_rectangle,font=("黑体", 12), fg="#FFFFFF", bg="#555555")update_button.grid(row=len(dimensions), column=0, columnspan=4, pady=10)# 日志区域log_frame = tk.LabelFrame(right_frame, text="操作日志", font=("黑体", 12), bg="#333333", fg="#FFFFFF")log_frame.pack(fill=tk.X, pady=(10, 5))self.log_text = scrolledtext.ScrolledText(log_frame, width=55, height=12,bg="#444444", fg="#FFFFFF", font=("Consolas", 10))self.log_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)self.log_text.insert(tk.END, "操作日志:\n")# 实时状态区域(分为两行,每行显示两组)status_frame = tk.LabelFrame(right_frame, text="实时状态", font=("黑体", 10), bg="#333333", fg="#FFFFFF")status_frame.pack(fill=tk.X, pady=(5, 10))self.status_labels = {"top": {"name": tk.Label(status_frame, text="上边:", bg="#333333", fg="#FFFFFF"),"status": tk.Label(status_frame, text="OK", bg="#333333", fg="#00FF00")},"right": {"name": tk.Label(status_frame, text="右边:", bg="#333333", fg="#FFFFFF"),"status": tk.Label(status_frame, text="OK", bg="#333333", fg="#00FF00")},"bottom": {"name": tk.Label(status_frame, text="下边:", bg="#333333", fg="#FFFFFF"),"status": tk.Label(status_frame, text="OK", bg="#333333", fg="#00FF00")},"left": {"name": tk.Label(status_frame, text="左边:", bg="#333333", fg="#FFFFFF"),"status": tk.Label(status_frame, text="OK", bg="#333333", fg="#00FF00")},}# 实时状态布局:两行,每行显示两组row1_keys = ["top"]row2_keys = ["right"]row3_keys = ["bottom"]row4_keys = ["left"]for i, key in enumerate(row1_keys):self.status_labels[key]["name"].grid(row=0, column=i*2, sticky="w", padx=(10,5), pady=2)self.status_labels[key]["status"].grid(row=0, column=i*2+1, sticky="w", padx=(5,10), pady=2)for i, key in enumerate(row2_keys):self.status_labels[key]["name"].grid(row=1, column=i*2, sticky="w", padx=(10,5), pady=2)self.status_labels[key]["status"].grid(row=1, column=i*2+1, sticky="w", padx=(5,10), pady=2)for i, key in enumerate(row3_keys):self.status_labels[key]["name"].grid(row=2, column=i*2, sticky="w", padx=(10,5), pady=2)self.status_labels[key]["status"].grid(row=2, column=i*2+1, sticky="w", padx=(5,10), pady=2)for i, key in enumerate(row4_keys):self.status_labels[key]["name"].grid(row=3, column=i*2, sticky="w", padx=(10,5), pady=2)self.status_labels[key]["status"].grid(row=3, column=i*2+1, sticky="w", padx=(5,10), pady=2)def img_update(self):"""实时图像更新逻辑"""img_dir = r"C:\Log\Picture\POL"try:if os.path.exists(img_dir):files = sorted([f for f in os.listdir(img_dir) if f.lower().endswith(('.png','.jpg','.bmp'))])if files:# 带缓存的图像加载path = os.path.join(img_dir, files[self.img_index % len(files)])with Image.open(path) as img:img = img.resize((280, 420), Image.Resampling.LANCZOS)  # 调整图像大小以适应列宽self.current_img = ImageTk.PhotoImage(img)self.img_label.config(image=self.current_img)self.img_index += 1except Exception as e:logging.error(f"图像加载异常: {str(e)}")finally:self.root.after(1000, self.img_update)  # 定时刷新def open_vision_system(self):"""打开视觉系统""" try:#vision_path = r"E:\Tim_Study\POL_Case\POLV1\Public_Release\POLV1.exe"vision_path = r"E:\Tim_Study\POL_Case\Vision\Public_Release\Vision.exe"if os.path.exists(vision_path):subprocess.Popen(vision_path)self.log_message("视觉系统已启动")else:messagebox.showerror("错误", f"未找到视觉系统程序: {vision_path}")self.log_message(f"视觉系统程序未找到: {vision_path}")except Exception as e:logging.error(f"启动视觉系统错误: {str(e)}")messagebox.showerror("错误", f"启动视觉系统失败: {e}")self.log_message(f"启动视觉系统错误: {e}")def log_message(self, message):timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")log_entry = f"{timestamp} - {message}\n"self.log_text.insert(tk.END, log_entry)self.log_text.see(tk.END)logging.info(message)def send_command(self):server_ip = "127.0.0.1"port = 7930try:self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.client_socket.connect((server_ip, port))self.client_socket.sendall(b"V1_Point_Draw")threading.Thread(target=self.receive_data).start()self.log_message("命令发送成功: V1_Point_Draw")# 更新结果展示区域状态self.result_label.config(text="测量中...", fg="#FFFF00")  # 黄色表示测量中self.detail_result_label.config(text="")except Exception as e:logging.error(f"连接错误 {e}")messagebox.showerror("错误", f"连接失败: {e}\n\n\n请先确认视觉系统")self.log_message(f"连接错误: {e}")# 更新结果展示区域状态self.result_label.config(text="连接失败", fg="#FF0000")  # 红色表示错误self.detail_result_label.config(text=str(e))def receive_data(self):try:while True:data = self.client_socket.recv(1024).decode('utf-8')if not data:breakself.update_ui(data)except Exception as e:logging.error(f"数据接收错误 {e}")messagebox.showerror("错误", f"数据接收失败: {e}")self.log_message(f"数据接收错误: {e}")# 更新结果展示区域状态self.result_label.config(text="接收错误", fg="#FF0000")self.detail_result_label.config(text=str(e))finally:self.client_socket.close()self.log_message("连接已关闭")def update_ui(self, data):self.draw_rectangle_with_dimensions(data)self.log_message(f"接收数据: {data}")# 更新结果展示区域self.update_result_display(data)def draw_rectangle_with_dimensions(self, data):try:self.canvas.delete("all")points = list(map(float, data.split(',')))if len(points) != 4:raise ValueError("数据格式错误,需要4个参数")# 绘制标准矩形self.draw_standard_rectangle()# 绘制实时矩形x1, y1 = 80, 100scale = min(1000 / max(points), 1)  # 自动缩放比例x2 = x1 + points[0] * scaley2 = y1 + points[1] * scaleself.canvas.create_rectangle(x1, y1, x2, y2, outline="#FF0000", width=2)# 实时矩形尺寸标注self.create_dimension_text((x1 + x2)/2, y1-30, f"{points[0]:.3f} mm", "#FF0000")self.create_dimension_text((x1 + x2)/2, y2+30, f"{points[2]:.3f} mm", "#FF0000")self.create_dimension_text(x1-30, (y1 + y2)/2, f"{points[3]:.3f} mm", "#FF0000", 90)self.create_dimension_text(x2+30, (y1 + y2)/2, f"{points[1]:.3f} mm", "#FF0000", 90)# 实时矩形中心显示"当前测量数据"self.canvas.create_text((x1 + x2)/2, (y1 + y2)/2, text="  ",fill="#FFFFFF", font=("Arial", 12), angle=90)# 更新实时状态self.update_status(points)except Exception as e:logging.error(f"绘图错误 {e}")messagebox.showerror("错误", f"绘图失败: {e}")self.log_message(f"绘图错误: {e}")# 更新结果展示区域状态self.result_label.config(text="绘图错误", fg="#FF0000")self.detail_result_label.config(text=str(e))def update_result_display(self, data):"""优化后的结果判断逻辑"""try:points = list(map(float, data.split(',')))if len(points) != 4:raise ValueError("需要4个测量参数")all_ok = Truedetails = []status_colors = {}for key, value in zip(["top", "right", "bottom", "left"], points):std = self.standard_dimensions[key]tol = self.standard_tolerances[f"{key}_tol"]diff = abs(value - std)if diff > tol:all_ok = Falsedetails.append(f"{key} 超差 {diff:.3f}mm")status_colors[key] = "#FF0000"else:details.append(f"{key} 合格 ±{diff:.3f}mm")status_colors[key] = "#00FF00"# 更新实时状态显示self.status_labels[key]["status"].config(text=f"{value:.3f}mm (标准{std:.3f}±{tol:.3f})",fg=status_colors[key])# 更新总体结果显示if all_ok:self.result_label.config(text="测量合格", fg="#00FF00")self.detail_result_label.config(text="所有尺寸均在公差范围内")else:self.result_label.config(text="测量不合格", fg="#FF0000")self.detail_result_label.config(text=" | ".join(details))except Exception as e:self.result_label.config(text="数据解析错误", fg="#FF0000")self.detail_result_label.config(text=str(e))logging.error(f"结果判断错误: {str(e)}")def draw_standard_rectangle(self):try:# 获取标准尺寸dimensions = {k: float(v.get()) for k, v in self.entries.items() if v.get()}if len(dimensions) != 4:return# 更新标准尺寸self.standard_dimensions = dimensions# 标准矩形参数std_x1, std_y1 = 80, 100scale = min(1000 / max(dimensions.values()), 1)  # 自动缩放比例std_x2 = std_x1 + dimensions['top'] * scalestd_y2 = std_y1 + dimensions['right'] * scale# 绘制标准矩形self.canvas.create_rectangle(std_x1, std_y1, std_x2, std_y2, outline="#00FF00", width=2)self.canvas.create_text((std_x1 + std_x2)/2, (std_y1 + std_y2)/2,text="白色标准值\n\n红色测量值", fill="#FFFFFF", font=("黑体", 14, "bold"))# 标准尺寸标注self.create_dimension_text((std_x1 + std_x2)/2, std_y1-10, f"{dimensions['top']:.3f} mm", "#FFFFFF")self.create_dimension_text((std_x1 + std_x2)/2, std_y2+10, f"{dimensions['bottom']:.3f} mm", "#FFFFFF")self.create_dimension_text(std_x1-10, (std_y1 + std_y2)/2, f"{dimensions['left']:.3f} mm", "#FFFFFF", 90)self.create_dimension_text(std_x2+10, (std_y1 + std_y2)/2, f"{dimensions['right']:.3f} mm", "#FFFFFF", 90)except ValueError:passdef create_dimension_text(self, x, y, text, color, angle=0):return self.canvas.create_text(x, y, text=text, fill=color,font=("Arial", 10), angle=angle, anchor=tk.CENTER)def update_status(self, real_time_data):# 获取公差值try:tolerances = {k: float(v.get()) for k, v in self.tolerance_entries.items() if v.get()}except ValueError:messagebox.showerror("错误", "请输入有效的公差值!")returnfor key, value in zip(["top", "right", "bottom", "left"], real_time_data):standard_value = self.standard_dimensions[key]tolerance = tolerances[f"{key}_tol"]  # 动态获取对应边的公差diff = abs(value - standard_value)if diff <= tolerance:status = "OK"color = "#00FF00"else:status = f"NG ({diff - tolerance:.3f} mm)"color = "#FF0000"# 更新状态标签self.status_labels[key]["status"].config(text=status, fg=color)def update_standard_rectangle(self):"""更新标准矩形尺寸和公差"""try:# 验证并获取标准尺寸standard_dimensions = {}required_keys = ["top", "right", "bottom", "left"]for key in required_keys:value = self.entries[key].get()if not value:raise ValueError(f"请填写{key}尺寸")standard_dimensions[key] = float(value)# 验证并获取公差值standard_tolerances = {}required_tols = ["top_tol", "right_tol", "bottom_tol", "left_tol"]for key in required_tols:value = self.tolerance_entries[key].get()if not value:raise ValueError(f"请填写{key}公差")standard_tolerances[key] = float(value)# 更新标准数据self.standard_dimensions = standard_dimensionsself.standard_tolerances = standard_tolerancesself.draw_standard_rectangle()self.log_message("标准数据更新成功")except ValueError as e:messagebox.showerror("输入错误", str(e))logging.error(f"标准数据更新失败: {str(e)}")if __name__ == "__main__":root = tk.Tk()app = IndustrialApp(root)root.mainloop()
import tkinter as tk
from tkinter import messagebox, scrolledtext
import socket
import threading
from datetime import datetime
import os
import logging
from PIL import Image, ImageTk
import subprocess# 定义文件夹路径
folder_path = r'c:\Log123'# 创建日志文件夹
if not os.path.exists(folder_path):os.makedirs(folder_path)# 设置日志记录
logging.basicConfig(filename=os.path.join(folder_path, 'log.log'), level=logging.INFO,format='%(asctime)s:%(levelname)s:%(message)s')class IndustrialApp:def __init__(self, root):self.root = rootself.root.title("Design_By_Tim")self.root.geometry("1200x700")self.root.configure(bg="#333333")# 图像加载相关变量self.img_index = 0self.current_img = None# 创建三列布局self.create_image_column()   # 左侧图像列self.create_control_column()  # 中间控制列self.create_status_column()   # 右侧状态列# 初始化网络连接self.client_socket = None self.standard_dimensions = {}self.standard_tolerances = {}self.update_standard_rectangle()  # 从输入框初始化标准数据# 启动图像更新self.img_update()def create_image_column(self):"""创建左侧图像列"""image_frame = tk.Frame(self.root, bg="#222222", width=400)image_frame.pack(side=tk.LEFT, fill=tk.BOTH, padx=(10,5), pady=10)image_frame.pack_propagate(False)  # 固定宽度# 图像显示标签self.img_label = tk.Label(image_frame, bg="#222222")self.img_label.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)# 视觉打开按钮vision_button = tk.Button(image_frame, text="打开视觉系统", command=self.open_vision_system,font=("黑体", 18, "bold"), fg="#FFFFFF", bg="#006699",relief=tk.RAISED, borderwidth=3)vision_button.pack(side=tk.TOP, fill=tk.X, padx=5, pady=5)def create_control_column(self):"""创建中间控制列"""control_frame = tk.Frame(self.root, bg="#333333")control_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=10)# 工业风启动按钮self.start_button = tk.Button(control_frame, text="开始测量", command=self.send_command,font=("黑体", 16, "bold"), fg="#FFFFFF", bg="#006699",relief=tk.RAISED, borderwidth=3, width=8)self.start_button.pack(side=tk.TOP, fill=tk.X, anchor=tk.NW, padx=10, pady=10)# 绘图画布self.canvas = tk.Canvas(control_frame, bg="#444444", highlightthickness=0)self.canvas.pack(fill=tk.BOTH, expand=True)# 新增: 醒目的判断结果展示区域self.result_frame = tk.Frame(control_frame, bg="#333333", height=80)self.result_frame.pack(fill=tk.X, pady=(10, 0))# 初始状态为"等待测量"self.result_label = tk.Label(self.result_frame, text="等待测量...", font=("黑体", 24, "bold"), bg="#333333", fg="#FFFFFF")self.result_label.pack(expand=True, fill=tk.BOTH)# 详细结果标签self.detail_result_label = tk.Label(self.result_frame, text="", font=("黑体", 12), bg="#333333", fg="#FFFFFF")self.detail_result_label.pack(fill=tk.X, pady=(0, 5))def create_status_column(self):"""创建右侧状态列"""right_frame = tk.Frame(self.root, bg="#333333", width=300)right_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=(5,10), pady=10)right_frame.pack_propagate(False)  # 固定宽度# 标准矩形设置区settings_frame = tk.LabelFrame(right_frame, text="标准设置", font=("黑体", 12),bg="#333333", fg="#FFFFFF")settings_frame.pack(pady=10, fill=tk.X, padx=(6, 0))# 尺寸输入框   315.021,131.784,315.085,132.322dimensions = [("上边 (mm):", "top", 315.021), ("右边 (mm):", "right", 131.784),("下边 (mm):", "bottom", 315.085), ("左边 (mm):", "left", 132.322)]self.entries = {}for i, (label, name, default_value) in enumerate(dimensions):tk.Label(settings_frame, text=label, bg="#333333", fg="#FFFFFF").grid(row=i, column=0, padx=5, pady=5)entry = tk.Entry(settings_frame, width=10)entry.grid(row=i, column=1, padx=5, pady=5)entry.insert(0, str(default_value))self.entries[name] = entry# 公差输入框tolerances = [("上边公差 (mm):", "top_tol", 0.1), ("右边公差 (mm):", "right_tol", 0.1),("下边公差 (mm):", "bottom_tol", 0.1), ("左边公差 (mm):", "left_tol", 0.1)]self.tolerance_entries = {}for i, (label, name, default_value) in enumerate(tolerances):tk.Label(settings_frame, text=label, bg="#333333", fg="#FFFFFF").grid(row=i, column=2, padx=5, pady=5)entry = tk.Entry(settings_frame, width=10)entry.grid(row=i, column=3, padx=5, pady=5)entry.insert(0, str(default_value))self.tolerance_entries[name] = entry# 更新按钮update_button = tk.Button(settings_frame, text="更新标准数据", command=self.update_standard_rectangle,font=("黑体", 12), fg="#FFFFFF", bg="#555555")update_button.grid(row=len(dimensions), column=0, columnspan=4, pady=10)# 日志区域log_frame = tk.LabelFrame(right_frame, text="操作日志", font=("黑体", 12), bg="#333333", fg="#FFFFFF")log_frame.pack(fill=tk.X, pady=(10, 5), padx=(6, 0))self.log_text = scrolledtext.ScrolledText(log_frame, width=55, height=12,bg="#444444", fg="#FFFFFF", font=("Consolas", 10))self.log_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)self.log_text.insert(tk.END, "操作日志:\n")# 实时状态区域(分为两行,每行显示两组)status_frame = tk.LabelFrame(right_frame, text="实时状态", font=("黑体", 10), bg="#333333", fg="#FFFFFF")status_frame.pack(fill=tk.X, pady=(5, 10), padx=(6, 0))self.status_labels = {"top": {"name": tk.Label(status_frame, text="上边:", bg="#333333", fg="#FFFFFF"),"status": tk.Label(status_frame, text="OK", bg="#333333", fg="#00FF00")},"right": {"name": tk.Label(status_frame, text="右边:", bg="#333333", fg="#FFFFFF"),"status": tk.Label(status_frame, text="OK", bg="#333333", fg="#00FF00")},"bottom": {"name": tk.Label(status_frame, text="下边:", bg="#333333", fg="#FFFFFF"),"status": tk.Label(status_frame, text="OK", bg="#333333", fg="#00FF00")},"left": {"name": tk.Label(status_frame, text="左边:", bg="#333333", fg="#FFFFFF"),"status": tk.Label(status_frame, text="OK", bg="#333333", fg="#00FF00")},}# 实时状态布局:两行,每行显示两组row1_keys = ["top"]row2_keys = ["right"]row3_keys = ["bottom"]row4_keys = ["left"]for i, key in enumerate(row1_keys):self.status_labels[key]["name"].grid(row=0, column=i*2, sticky="w", padx=(10,5), pady=2)self.status_labels[key]["status"].grid(row=0, column=i*2+1, sticky="w", padx=(5,10), pady=2)for i, key in enumerate(row2_keys):self.status_labels[key]["name"].grid(row=1, column=i*2, sticky="w", padx=(10,5), pady=2)self.status_labels[key]["status"].grid(row=1, column=i*2+1, sticky="w", padx=(5,10), pady=2)for i, key in enumerate(row3_keys):self.status_labels[key]["name"].grid(row=2, column=i*2, sticky="w", padx=(10,5), pady=2)self.status_labels[key]["status"].grid(row=2, column=i*2+1, sticky="w", padx=(5,10), pady=2)for i, key in enumerate(row4_keys):self.status_labels[key]["name"].grid(row=3, column=i*2, sticky="w", padx=(10,5), pady=2)self.status_labels[key]["status"].grid(row=3, column=i*2+1, sticky="w", padx=(5,10), pady=2)def img_update(self):"""实时图像更新逻辑"""img_dir = r"C:\Log\Picture\POL"try:if os.path.exists(img_dir):files = sorted([f for f in os.listdir(img_dir) if f.lower().endswith(('.png','.jpg','.bmp'))])if files:# 带缓存的图像加载path = os.path.join(img_dir, files[self.img_index % len(files)])with Image.open(path) as img:img = img.resize((280, 420), Image.Resampling.LANCZOS)  # 调整图像大小以适应列宽self.current_img = ImageTk.PhotoImage(img)self.img_label.config(image=self.current_img)self.img_index += 1except Exception as e:logging.error(f"图像加载异常: {str(e)}")finally:self.root.after(1000, self.img_update)  # 定时刷新def open_vision_system(self):"""打开视觉系统""" try:#vision_path = r"E:\Tim_Study\POL_Case\POLV1\Public_Release\POLV1.exe"vision_path = r"E:\Tim_Study\POL_Case\Vision\Public_Release\Vision.exe"if os.path.exists(vision_path):subprocess.Popen(vision_path)self.log_message("视觉系统已启动")else:messagebox.showerror("错误", f"未找到视觉系统程序: {vision_path}")self.log_message(f"视觉系统程序未找到: {vision_path}")except Exception as e:logging.error(f"启动视觉系统错误: {str(e)}")messagebox.showerror("错误", f"启动视觉系统失败: {e}")self.log_message(f"启动视觉系统错误: {e}")def log_message(self, message):timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")log_entry = f"{timestamp} - {message}\n"self.log_text.insert(tk.END, log_entry)self.log_text.see(tk.END)logging.info(message)def send_command(self):server_ip = "127.0.0.1"port = 7930try:self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.client_socket.connect((server_ip, port))self.client_socket.sendall(b"V1_Point_Draw")threading.Thread(target=self.receive_data).start()self.log_message("命令发送成功: V1_Point_Draw")# 更新结果展示区域状态self.result_label.config(text="测量中...", fg="#FFFF00")  # 黄色表示测量中self.detail_result_label.config(text="")except Exception as e:logging.error(f"连接错误 {e}")messagebox.showerror("错误", f"连接失败: {e}\n\n\n请先确认视觉系统")self.log_message(f"连接错误: {e}")# 更新结果展示区域状态self.result_label.config(text="连接失败", fg="#FF0000")  # 红色表示错误self.detail_result_label.config(text=str(e))def receive_data(self):try:while True:data = self.client_socket.recv(1024).decode('utf-8')if not data:breakself.update_ui(data)except Exception as e:logging.error(f"数据接收错误 {e}")messagebox.showerror("错误", f"数据接收失败: {e}")self.log_message(f"数据接收错误: {e}")# 更新结果展示区域状态self.result_label.config(text="接收错误", fg="#FF0000")self.detail_result_label.config(text=str(e))finally:self.client_socket.close()self.log_message("连接已关闭")def update_ui(self, data):self.draw_rectangle_with_dimensions(data)self.log_message(f"接收数据: {data}")# 更新结果展示区域self.update_result_display(data)def draw_rectangle_with_dimensions(self, data):try:self.canvas.delete("all")points = list(map(float, data.split(',')))if len(points) != 4:raise ValueError("数据格式错误,需要4个参数")# 绘制标准矩形self.draw_standard_rectangle()# 绘制实时矩形x1, y1 = 80, 100scale = min(1000 / max(points), 1)  # 自动缩放比例x2 = x1 + points[0] * scaley2 = y1 + points[1] * scaleself.canvas.create_rectangle(x1, y1, x2, y2, outline="#FF0000", width=2)# 实时矩形尺寸标注self.create_dimension_text((x1 + x2)/2, y1-30, f"{points[0]:.3f} mm", "#FF0000")self.create_dimension_text((x1 + x2)/2, y2+30, f"{points[2]:.3f} mm", "#FF0000")self.create_dimension_text(x1-30, (y1 + y2)/2, f"{points[3]:.3f} mm", "#FF0000", 90)self.create_dimension_text(x2+30, (y1 + y2)/2, f"{points[1]:.3f} mm", "#FF0000", 90)# 实时矩形中心显示"当前测量数据"self.canvas.create_text((x1 + x2)/2, (y1 + y2)/2, text="  ",fill="#FFFFFF", font=("Arial", 12), angle=90)# 更新实时状态self.update_status(points)except Exception as e:logging.error(f"绘图错误 {e}")messagebox.showerror("错误", f"绘图失败: {e}")self.log_message(f"绘图错误: {e}")# 更新结果展示区域状态self.result_label.config(text="绘图错误", fg="#FF0000")self.detail_result_label.config(text=str(e))def update_result_display(self, data):"""优化后的结果判断逻辑"""try:points = list(map(float, data.split(',')))if len(points) != 4:raise ValueError("需要4个测量参数")all_ok = Truedetails = []status_colors = {}for key, value in zip(["top", "right", "bottom", "left"], points):std = self.standard_dimensions[key]tol = self.standard_tolerances[f"{key}_tol"]diff = abs(value - std)if diff > tol:all_ok = Falsedetails.append(f"{key} 超差 {diff:.3f}mm")status_colors[key] = "#FF0000"else:details.append(f"{key} 合格 ±{diff:.3f}mm")status_colors[key] = "#00FF00"# 更新实时状态显示self.status_labels[key]["status"].config(text=f"{value:.3f}mm (标准{std:.3f}±{tol:.3f})",fg=status_colors[key])# 更新总体结果显示if all_ok:self.result_label.config(text="测量合格", fg="#00FF00")self.detail_result_label.config(text="所有尺寸均在公差范围内")else:self.result_label.config(text="测量不合格", fg="#FF0000")self.detail_result_label.config(text=" | ".join(details))except Exception as e:self.result_label.config(text="数据解析错误", fg="#FF0000")self.detail_result_label.config(text=str(e))logging.error(f"结果判断错误: {str(e)}")def draw_standard_rectangle(self):try:# 获取标准尺寸dimensions = {k: float(v.get()) for k, v in self.entries.items() if v.get()}if len(dimensions) != 4:return# 更新标准尺寸self.standard_dimensions = dimensions# 标准矩形参数std_x1, std_y1 = 80, 100scale = min(1000 / max(dimensions.values()), 1)  # 自动缩放比例std_x2 = std_x1 + dimensions['top'] * scalestd_y2 = std_y1 + dimensions['right'] * scale# 绘制标准矩形self.canvas.create_rectangle(std_x1, std_y1, std_x2, std_y2, outline="#00FF00", width=2)self.canvas.create_text((std_x1 + std_x2)/2, (std_y1 + std_y2)/2,text="白色标准值\n\n红色测量值", fill="#FFFFFF", font=("黑体", 14, "bold"))# 标准尺寸标注self.create_dimension_text((std_x1 + std_x2)/2, std_y1-10, f"{dimensions['top']:.3f} mm", "#FFFFFF")self.create_dimension_text((std_x1 + std_x2)/2, std_y2+10, f"{dimensions['bottom']:.3f} mm", "#FFFFFF")self.create_dimension_text(std_x1-10, (std_y1 + std_y2)/2, f"{dimensions['left']:.3f} mm", "#FFFFFF", 90)self.create_dimension_text(std_x2+10, (std_y1 + std_y2)/2, f"{dimensions['right']:.3f} mm", "#FFFFFF", 90)except ValueError:passdef create_dimension_text(self, x, y, text, color, angle=0):return self.canvas.create_text(x, y, text=text, fill=color,font=("Arial", 10), angle=angle, anchor=tk.CENTER)def update_status(self, real_time_data):# 获取公差值try:tolerances = {k: float(v.get()) for k, v in self.tolerance_entries.items() if v.get()}except ValueError:messagebox.showerror("错误", "请输入有效的公差值!")returnfor key, value in zip(["top", "right", "bottom", "left"], real_time_data):standard_value = self.standard_dimensions[key]tolerance = tolerances[f"{key}_tol"]  # 动态获取对应边的公差diff = abs(value - standard_value)if diff <= tolerance:status = "OK"color = "#00FF00"else:status = f"NG ({diff - tolerance:.3f} mm)"color = "#FF0000"# 更新状态标签self.status_labels[key]["status"].config(text=status, fg=color)def update_standard_rectangle(self):"""更新标准矩形尺寸和公差"""try:# 验证并获取标准尺寸standard_dimensions = {}required_keys = ["top", "right", "bottom", "left"]for key in required_keys:value = self.entries[key].get()if not value:raise ValueError(f"请填写{key}尺寸")standard_dimensions[key] = float(value)# 验证并获取公差值standard_tolerances = {}required_tols = ["top_tol", "right_tol", "bottom_tol", "left_tol"]for key in required_tols:value = self.tolerance_entries[key].get()if not value:raise ValueError(f"请填写{key}公差")standard_tolerances[key] = float(value)# 更新标准数据self.standard_dimensions = standard_dimensionsself.standard_tolerances = standard_tolerancesself.draw_standard_rectangle()self.log_message("标准数据更新成功")except ValueError as e:messagebox.showerror("输入错误", str(e))logging.error(f"标准数据更新失败: {str(e)}")if __name__ == "__main__":root = tk.Tk()app = IndustrialApp(root)root.mainloop()

相关文章:

  • 【开源】STM32HAL库移植Arduino OneWire库驱动DS18B20和MAX31850
  • 香港科技大学广州|先进材料学域博士招生宣讲会—南开大学专场
  • OpenCV 图形API(54)颜色空间转换-----将图像从 RGB 色彩空间转换到 HSV色彩空间RGB2HSV()
  • day001
  • 计算机网络笔记(七)——1.7计算机网络体系结构
  • 无穿戴动捕:突破穿戴式设备束缚,解锁更自由高效的动作捕捉体验
  • Linux/AndroidOS中进程间的通信线程间的同步 - IPC方式简介
  • 智能配送机器人控制系统设计
  • MySQL 8.4企业版 安装和配置审计插件
  • 0422--在网页中上传头像(图片)
  • ChatBEV:一种理解 BEV 地图的可视化语言模型
  • 【论文阅读25】-滑坡时间预测-PFTF
  • 解耦旧系统的利器:Java 中的适配器模式(Adapter Pattern)实战解析
  • bert4keras
  • UV: Python包和项目管理器(从入门到不放弃教程)
  • SQL 时间转换的CONVERT()函数应用说明
  • 实验二 多线程编程实验
  • [蓝桥杯 2025 省 Python B] 最多次数
  • HashedWheelTimer源码分析
  • Scrapy框架爬虫官网的学习
  • 宝龙地产:委任中金国际为境外债务重组新的独家财务顾问
  • “中华优秀科普图书榜”2024年度榜单揭晓
  • 最高检:去年共受理审查逮捕侵犯知识产权犯罪13486人
  • 国际货币基金组织:将今年美国经济增长预期下调0.9个百分点至1.8%
  • 《哪吒2》票房已达157亿,光线传媒一季度净利增至20亿元
  • 乍嘉苏改扩建项目迎来新进展!预应力管桩首件施工顺利完成