在線測試來料公差


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()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80307.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80307.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80307.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【優秀三方庫研讀】【C++基礎知識】odygrd/quill -- 折疊表達式

compute_encoded_size_and_cache_string_lengths 方法中這段代碼是一個C的折疊表達式&#xff08;fold expression&#xff09;的應用&#xff0c;用于計算多個參數編碼后的總大小。下面我將詳細解釋這段代碼的每個部分&#xff0c;并說明為什么這樣寫。 代碼如下&#xff1a; …

數據庫安裝和升級和雙主配置

備份和導入數據 ./mysqldump -u root -p123321 test > test.sql rsync -av test.sql root192.168.0.212:/usr/local/mysql/ ./mysql -uroot -p test < …/test.sql sudo tar -zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz -C /usr/local/ sudo ln -sfn /usr/loca…

【C語言】條件編譯

&#x1f984;個人主頁:修修修也 &#x1f38f;所屬專欄:C語言 ??操作環境:Visual Studio 2022 目錄 條件編譯 常用的預處理指令 核心應用場景 1.防止頭文件重復包含 2.跨平臺兼容性 3.調試模式與發布模式 4.功能開關 5.代碼兼容性處理 結語 條件編譯 一般情況下,源程序中所有…

如何在安卓平板上下載安裝Google Chrome【輕松安裝】

安卓平板可以通過系統內置的應用商店直接搜索并下載谷歌瀏覽器。用戶打開平板上的“Play 商店”&#xff0c;在搜索框輸入Google Chrome。出現結果后&#xff0c;點擊第一個帶有“Google LLC”字樣的應用圖標&#xff0c;然后點“安裝”按鈕。下載和安裝時間和網速有關&#xf…

.NET代碼保護混淆和軟件許可系統——Eziriz .NET Reactor 7

.NET代碼保護混淆和軟件許可系統——Eziriz .NET Reactor 7 1、簡介2、功能特點3、知識產權保護功能4、強大的許可系統5、軟件開發工具包6、部署方式7、下載 1、簡介 .NET Reactor是用于為.NET Framework編寫的軟件的功能強大的代碼保護和軟件許可系統&#xff0c;并且支持生成…

利用 SSE 實現文字吐字效果:技術與實踐

利用 SSE 實現文字吐字效果:技術與實踐 引言 在現代 Web 應用開發中,實時交互功能愈發重要。例如,在線聊天、實時數據監控、游戲中的實時更新等場景,都需要服務器能夠及時將數據推送給客戶端。傳統的請求 - 響應模式在處理實時性要求較高的場景時顯得力不從心,而 Server…

一個簡單易用的密碼生成器

基于瀏覽器的確定性密碼生成工具&#xff0c;通過用戶輸入的網站名稱和鹽值生成符合安全要求的密碼。特點&#xff1a; ? 相同輸入始終生成相同密碼 ? 密碼自動包含大小寫字母、數字和特殊符號 ? 以字母開頭&#xff0c;固定8位長度 ? 完全在客戶端運行&#xff0c;保護…

水上與水下遙控技術要點對比

1. 水上無人機遙控器技術要點 (1) 控制方式 多通道控制&#xff1a;通常使用2.4GHz或5.8GHz無線電信號&#xff0c;支持多通道&#xff08;如4通道以上&#xff09;分別控制飛行器的姿態&#xff08;俯仰、橫滾、偏航&#xff09;和油門。 高級飛行模式&#xff1a;如定高模…

Android_SDK鏈接 雷神模擬器(端口問題) --- app筆記

調試環境&#xff1a;JDK&#xff08;java&#xff09; SDK&#xff08;android&#xff09; Node.js 雷神模擬器&#xff08;或 真機&#xff09; Appium&#xff08;Appium Server【內外件&#xff08;dos內件、界面化工具&#xff09;】、Appium Inspector&#xff09; p…

FreeRTOS【3】任務調度算法

重要概念 在運行的任務&#xff0c;被稱為"正在使用處理器"&#xff0c;它處于運行狀態。在單處理系統中&#xff0c;任何時間里只能有一個任務處于運行狀態。 非運行狀態的任務&#xff0c;它處于這 3 中狀態之一&#xff1a;阻塞(Blocked)、暫停(Suspended)、就緒…

SLAM常用地圖對比示例

序號地圖類型概述1格柵地圖將現實環境柵格化&#xff0c;每一個柵格用 0 和 1 分別表示空閑和占據狀態&#xff0c;初始化為未知狀態 0.52特征地圖以點、線、面等幾何特征來描繪周圍環境&#xff0c;將采集的信息進行篩選和提取得到關鍵幾何特征3拓撲地圖將重要部分抽象為地圖&…

【Vue】TypeScript與Vue3集成

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;Vue 文章目錄 1. 前言2. 環境準備與基礎搭建2.1. 安裝 Node.js 與 npm/yarn/pnpm2.2. 創建 Vue3 TypeScript 項目2.2.1. 使用 Vue CLI2.2.2. 使用 Vite&#xff08;推薦&#xff09;2.2.3. 目錄結構簡述 3. Vue3 TS 基礎語法整…

高防IP是什么

"高防IP"是指"高防護IP"&#xff0c;是一種防御DDoS&#xff08;分布式拒絕服務攻擊&#xff09;的網絡安全服務。在分布式拒絕服務攻擊中&#xff0c;攻擊者會利用許多不同的計算機或者其他設備&#xff0c;通過向目標發送大量的網絡請求來嘗試使目標服務…

手機訪問電腦端Nginx服務器配置方式

修改當前站點Nginx的配置如下。其中端口號必須是一個比較獨特的端口號&#xff0c;比如8001。這樣可以跟別的項目區分開來。域名使用0.0.0.0。 server {listen 80;listen 8001;server_name zfmap.cc 0.0.0.0;假設你電腦端的ip地址是192.168.1.101,那么你的手機與你的電腦連在同…

【算法】計數排序、桶排序、基數排序

算法系列八&#xff1a;非比較排序 一、計數排序 1.實現 1.1步驟 1.2代碼 2.性質 2.1穩定性 2.1.1從前往后前始版&#xff1a; 2.1.2從后往前末始版&#xff1a; 2.2復雜度 2.2.1時間復雜度 2.2.2空間復雜度 二、桶排序 1.實現 1.1步驟 1.2代碼 2.穩定性 三、…

JDK版本與Spring Boot版本之間對應關系

JDK&#xff08;Java Development Kit&#xff09;版本與Spring Boot版本之間存在一定的對應關系&#xff0c;選擇合適的搭配對項目的穩定性、性能及功能實現至關重要&#xff0c;以下是詳細介紹&#xff1a; 主要版本對應關系 Spring Boot版本發布日期支持的JDK版本備注3.2.…

如何檢測Python項目哪些依賴庫沒有使用

要檢測Python項目中哪些依賴庫未被使用&#xff0c;可以采用以下方法&#xff1a; 1. 使用靜態分析工具 vulture&#xff1a;靜態分析工具&#xff0c;檢測未使用的代碼和導入 pip install vulture vulture your_project/pyflakes&#xff1a;檢查未使用的導入語句 pip ins…

【智能指針】—— 我與C++的不解之緣(三十三)

一、智能指針的使用 還記得&#xff0c;在異常學習的時候&#xff0c;我們分析出了一個問題 double Divide(int x, int y) {if (y 0){throw string("the y is zero");}return (double)x / double(y); } void test(int x, int y) {int* arr new int[10];Divide(x,…

Hadoop+Spark 筆記 2025/4/21

讀書筆記 定義 1. 大數據&#xff08;Big Data&#xff09; - 指傳統數據處理工具難以處理的海量、高速、多樣的數據集合&#xff0c;通常具備3V特性&#xff08;Volume體量大、Velocity速度快、Variety多樣性&#xff09;。擴展后還包括Veracity&#xff08;真實性&#x…

femap許可不足如何解決

在復雜的工程仿真領域&#xff0c;Femap以其強大的功能和廣泛的應用場景而備受青睞。然而&#xff0c;隨著用戶需求的增長和項目規模的擴大&#xff0c;Femap許可不足的問題逐漸凸顯&#xff0c;成為了許多工程師和團隊面臨的挑戰。本文將為您詳細解析Femap許可不足的原因&…