先上图
代码
import tkinter as tk
from tkinter import messagebox, scrolledtext
import socket
import threading
from datetime import datetime
import os
import logging
# 定义文件夹路径
folder_path = r'c:\Log'
# 创建日志文件夹
if not os.path.exists(folder_path):
os.makedirs(folder_path)
# 设置日志记录
logging.basicConfig(filename=os.path.join(folder_path, 'app.log'), level=logging.INFO,
format='%(asctime)s:%(levelname)s:%(message)s')
class IndustrialApp:
def __init__(self, root):
self.root = root
self.root.title("POL_Design_By_Tim")
self.root.geometry("800x600")
self.root.configure(bg="#333333")
# 左侧控制区
left_frame = tk.Frame(self.root, bg="#333333")
left_frame.pack(side=tk.LEFT, padx=20, pady=20, fill=tk.BOTH, expand=True)
# 工业风启动按钮
self.start_button = tk.Button(left_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, anchor=tk.NW, padx=10, pady=10)
# 绘图画布
self.canvas = tk.Canvas(left_frame, bg="#444444", highlightthickness=0)
self.canvas.pack(fill=tk.BOTH, expand=True)
# 右侧控制面板
right_frame = tk.Frame(self.root, bg="#333333")
right_frame.pack(side=tk.RIGHT, padx=20, pady=20, fill=tk.Y)
# 标准矩形设置区
settings_frame = tk.LabelFrame(right_frame, text="标准设置", font=("黑体", 12),
bg="#333333", fg="#FFFFFF")
settings_frame.pack(pady=10, fill=tk.X)
# 尺寸输入框
dimensions = [("上边 (mm):", "top", 132.452), ("右边 (mm):", "right", 314.632),
("下边 (mm):", "bottom", 134.145), ("左边 (mm):", "left", 314.361)]
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=8, # 缩小高度
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", "right"]
row2_keys = ["bottom", "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)
# 初始化网络连接
self.client_socket = None
self.standard_dimensions = {"top": 132.452, "right": 314.632, "bottom": 134.145, "left": 314.361}
self.standard_tolerances = {"top_tol": 0.5, "right_tol": 0.5, "bottom_tol": 0.5, "left_tol": 0.5}
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 = 7930
try:
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")
except Exception as e:
logging.error(f"连接错误 {e}")
messagebox.showerror("错误", f"连接失败: {e}")
self.log_message(f"连接错误: {e}")
def receive_data(self):
try:
while True:
data = self.client_socket.recv(1024).decode('utf-8')
if not data:
break
self.update_ui(data)
except Exception as e:
logging.error(f"数据接收错误 {e}")
messagebox.showerror("错误", f"数据接收失败: {e}")
self.log_message(f"数据接收错误: {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}")
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 = 100, 100
scale = min(1000 / max(points), 1) # 自动缩放比例
x2 = x1 + points[0] * scale
y2 = y1 + points[1] * scale
self.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}")
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 = 100, 100
scale = min(1000 / max(dimensions.values()), 1) # 自动缩放比例
std_x2 = std_x1 + dimensions['top'] * scale
std_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:
pass
def 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("错误", "请输入有效的公差值!")
return
for 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:
# 更新标准矩形尺寸
self.standard_dimensions = {k: float(v.get()) for k, v in self.entries.items() if v.get()}
self.standard_tolerances = {k: float(v.get()) for k, v in self.tolerance_entries.items() if v.get()}
self.draw_standard_rectangle()
self.log_message("更新标准矩形尺寸和公差")
except ValueError:
messagebox.showerror("错误", "请输入有效的数字!")
if __name__ == "__main__":
root = tk.Tk()
app = IndustrialApp(root)
root.mainloop()