cjf160204 发表于 3 天前

测量计算工具

import tkinter as tk
from tkinter import ttk, messagebox, Menu
import math
import uuid
from tkinter import scrolledtext

class MultiToolApplication:
    def __init__(self, master):
      self.master = master
      master.title("测量计算工具 v1.0")
      master.geometry("1000x800")
      master.resizable(True, True)

      # 样式配置
      self.style = ttk.Style()
      self.style.configure('TFrame', background='#f0f0f0')
      self.style.configure('TLabel', background='#f0f0f0', font=('微软雅黑', 10))
      self.style.configure('TButton', font=('微软雅黑', 10))
      self.style.configure('TRadiobutton', background='#f0f0f0', font=('微软雅黑', 10))
      self.style.configure('TLabelframe', font=('微软雅黑', 10, 'bold'))
      self.style.configure('TNotebook', background='#f0f0f0')
      self.style.configure('TNotebook.Tab', font=('微软雅黑', 10, 'bold'))

      # 主容器
      self.main_frame = ttk.Frame(master, padding="10")
      self.main_frame.pack(fill=tk.BOTH, expand=True)

      # 标题
      self.title_label = ttk.Label(
            self.main_frame,
            text="测量计算工具",
            font=('微软雅黑', 16, 'bold'),
            foreground='#0066cc'
      )
      self.title_label.pack(pady=(0, 10))

      # 创建标签页容器
      self.notebook = ttk.Notebook(self.main_frame)
      self.notebook.pack(fill=tk.BOTH, expand=True)

      # 创建各个工具页面
      self.create_measurement_calculator_tab()
      self.create_geometry_calculator_tab()
      self.create_leveling_calculator_tab()
      self.create_area_converter_tab()

      # 状态栏
      self.status_var = tk.StringVar()
      self.status_bar = ttk.Label(
            self.main_frame,
            textvariable=self.status_var,
            relief=tk.SUNKEN,
            anchor=tk.W
      )
      self.status_bar.pack(fill=tk.X, pady=(5, 0))
      self.status_var.set("就绪 | 请选择工具并输入参数")

    def create_measurement_calculator_tab(self):
      """创建测量计算工具标签页"""
      tab = ttk.Frame(self.notebook)
      self.notebook.add(tab, text="测量计算")

      # 操作选择区域
      self.measurement_operation_frame = ttk.LabelFrame(
            tab,
            text="选择计算类型",
            padding="10"
      )
      self.measurement_operation_frame.pack(fill=tk.X, pady=(0, 10))

      self.measurement_operation_var = tk.IntVar(value=1)

      operations = [
            ("1. 竖直角和指标差", 1),
            ("2. 三角高程高差", 2),
            ("3. 坐标正算", 3),
            ("4. 坐标反算", 4),
            ("5. 2c值计算", 5)
      ]

      for i, (text, val) in enumerate(operations):
            rb = ttk.Radiobutton(
                self.measurement_operation_frame,
                text=text,
                variable=self.measurement_operation_var,
                value=val,
                command=self.measurement_operation_changed
            )
            rb.grid(row=0, column=i, padx=5, sticky="w")

      # 输入区域
      self.measurement_input_frame = ttk.LabelFrame(
            tab,
            text="输入参数",
            padding="10"
      )
      self.measurement_input_frame.pack(fill=tk.BOTH, expand=True, pady=5)

      # 结果区域
      self.measurement_result_frame = ttk.LabelFrame(
            tab,
            text="计算结果",
            padding="10"
      )
      self.measurement_result_frame.pack(fill=tk.BOTH, expand=True, pady=5)

      self.measurement_result_text = scrolledtext.ScrolledText(
            self.measurement_result_frame,
            width=55,
            height=10,
            font=('Consolas', 10),
            wrap=tk.WORD,
            bg='#f9f9f9',
            relief=tk.SOLID,
            borderwidth=1
      )
      self.measurement_result_text.pack(fill=tk.BOTH, expand=True)
      self.measurement_result_text.insert(tk.END, "【计算结果】\n" + "="*40 + "\n")

      # 按钮区域
      self.measurement_button_frame = ttk.Frame(tab)
      self.measurement_button_frame.pack(pady=(10, 0))

      self.measurement_calculate_btn = ttk.Button(
            self.measurement_button_frame,
            text="计算",
            command=self.measurement_calculate
      )
      self.measurement_calculate_btn.pack(side=tk.LEFT, padx=5)

      self.measurement_clear_btn = ttk.Button(
            self.measurement_button_frame,
            text="清空",
            command=self.measurement_clear_all
      )
      self.measurement_clear_btn.pack(side=tk.LEFT, padx=5)

      # 默认显示第一个操作的输入字段
      self.current_measurement_operation = 1
      self.create_measurement_input_fields()

    def measurement_operation_changed(self):
      """测量计算类型改变时更新输入字段"""
      new_operation = self.measurement_operation_var.get()
      if new_operation != self.current_measurement_operation:
            self.current_measurement_operation = new_operation
            self.create_measurement_input_fields()
            self.measurement_clear_result()
            self.status_var.set(f"已选择: {self.get_measurement_operation_name()} | 请输入参数")

    def get_measurement_operation_name(self):
      """获取当前测量操作名称"""
      names = {
            1: "竖直角和指标差计算",
            2: "三角高程高差计算",
            3: "坐标正算",
            4: "坐标反算",
            5: "2c值计算"
      }
      return names.get(self.current_measurement_operation, "")

    def create_measurement_input_fields(self):
      """根据当前测量操作创建输入字段"""
      # 清除旧的输入字段
      for widget in self.measurement_input_frame.winfo_children():
            widget.destroy()

      # 创建新的输入字段
      if self.current_measurement_operation == 1:# 竖直角和指标差
            self.create_measurement_dms_input("左天顶距", 0)
            self.create_measurement_dms_input("右天顶距", 3)

      elif self.current_measurement_operation == 2:# 三角高程高差
            self.create_measurement_single_input("水平距离 (m)", 0)
            self.create_measurement_dms_input("垂直角", 1)
            self.create_measurement_single_input("仪器高 (m)", 4)
            self.create_measurement_single_input("棱镜高 (m)", 5)

      elif self.current_measurement_operation == 3:# 坐标正算
            self.create_measurement_single_input("起点X坐标", 0)
            self.create_measurement_single_input("起点Y坐标", 1)
            self.create_measurement_single_input("边长 (m)", 2)
            self.create_measurement_dms_input("方位角", 3)

      elif self.current_measurement_operation == 4:# 坐标反算
            self.create_measurement_single_input("点1 X坐标", 0)
            self.create_measurement_single_input("点1 Y坐标", 1)
            self.create_measurement_single_input("点2 X坐标", 2)
            self.create_measurement_single_input("点2 Y坐标", 3)
            self.create_measurement_single_input("点3 X坐标", 4)
            self.create_measurement_single_input("点3 Y坐标", 5)

      elif self.current_measurement_operation == 5:# 计算2c值
            self.create_measurement_dms_input("盘左读数", 0)
            self.create_measurement_dms_input("盘右读数", 3)

    def create_measurement_single_input(self, label_text, row):
      """创建单个输入字段"""
      frame = ttk.Frame(self.measurement_input_frame)
      frame.grid(row=row, column=0, sticky="ew", pady=2)

      label = ttk.Label(frame, text=label_text, width=15, anchor="e")
      label.pack(side=tk.LEFT, padx=5)

      entry = ttk.Entry(frame, width=15)
      entry.pack(side=tk.LEFT, fill=tk.X, expand=True)

      # 存储输入框引用
      setattr(self, f"measurement_entry_{row}", entry)

    def create_measurement_dms_input(self, label_text, start_row):
      """创建度分秒输入字段组"""
      frame = ttk.Frame(self.measurement_input_frame)
      frame.grid(row=start_row, column=0, sticky="ew", pady=2)

      # 标签
      label = ttk.Label(frame, text=f"{label_text}:", width=15, anchor="e")
      label.pack(side=tk.LEFT, padx=5)

      # 度
      subframe = ttk.Frame(frame)
      subframe.pack(side=tk.LEFT, fill=tk.X, expand=True)

      ttk.Label(subframe, text="度").pack(side=tk.LEFT)
      entry_deg = ttk.Entry(subframe, width=5)
      entry_deg.pack(side=tk.LEFT, padx=2)

      # 分
      ttk.Label(subframe, text="分").pack(side=tk.LEFT)
      entry_min = ttk.Entry(subframe, width=5)
      entry_min.pack(side=tk.LEFT, padx=2)

      # 秒
      ttk.Label(subframe, text="秒").pack(side=tk.LEFT)
      entry_sec = ttk.Entry(subframe, width=6)
      entry_sec.pack(side=tk.LEFT, padx=2)

      # 存储输入框引用
      setattr(self, f"measurement_entry_{start_row}_deg", entry_deg)
      setattr(self, f"measurement_entry_{start_row}_min", entry_min)
      setattr(self, f"measurement_entry_{start_row}_sec", entry_sec)

    def measurement_get_dms_value(self, base_name):
      """获取度分秒值并转换为十进制"""
      try:
            deg = float(getattr(self, f"measurement_entry_{base_name}_deg").get())
            minutes = float(getattr(self, f"measurement_entry_{base_name}_min").get())
            seconds = float(getattr(self, f"measurement_entry_{base_name}_sec").get())
            return self.dms_to_decimal(deg, minutes, seconds)
      except ValueError:
            raise ValueError(f"请输入有效的度分秒数值: {base_name}")

    def measurement_get_single_value(self, entry_name):
      """获取单个输入值"""
      try:
            value = getattr(self, f"measurement_entry_{entry_name}").get()
            if not value:
                raise ValueError("输入不能为空")
            return float(value)
      except ValueError:
            raise ValueError(f"请输入有效的数值: {entry_name}")

    def measurement_calculate(self):
      """执行测量计算"""
      try:
            self.measurement_clear_result()
            self.status_var.set("计算中...")
            self.master.update()

            if self.current_measurement_operation == 1:# 竖直角和指标差
                L = self.measurement_get_dms_value(0)
                R = self.measurement_get_dms_value(3)

                alpha_left = 90 - L
                alpha_right = R - 270
                index_error = (L + R - 360) / 2
                average_angle = (alpha_left + alpha_right) / 2

                self.measurement_append_result("■ 盘左竖直角 α(左)", alpha_left, "°")
                self.measurement_append_result("■ 盘右竖直角 α(右)", alpha_right, "°")
                self.measurement_append_result("■ 平均竖直角", average_angle, "°")
                self.measurement_append_result("■ 指标差", index_error, "°")

            elif self.current_measurement_operation == 2:# 三角高程高差
                distance = self.measurement_get_single_value(0)
                angle = self.measurement_get_dms_value(1)
                instrument_height = self.measurement_get_single_value(4)
                target_height = self.measurement_get_single_value(5)

                rad = math.radians(angle)
                tan_alpha = math.tan(rad)
                h_prime = distance * tan_alpha
                h_AB = h_prime + instrument_height - target_height

                self.measurement_append_result("■ 水平距离", distance, "m")
                self.measurement_append_result("■ 垂直角", angle, "°")
                self.measurement_append_result("■ 初算高差 h' = D·tanα", h_prime, "m")
                self.measurement_append_result("■ 最终高差 h = h' + i - v", h_AB, "m")

            elif self.current_measurement_operation == 3:# 坐标正算
                x_a = self.measurement_get_single_value(0)
                y_a = self.measurement_get_single_value(1)
                d_ab = self.measurement_get_single_value(2)
                angle = self.measurement_get_dms_value(3)

                angle_rad = math.radians(angle)
                x_b = x_a + d_ab * math.cos(angle_rad)
                y_b = y_a + d_ab * math.sin(angle_rad)

                self.measurement_append_result("■ 起点坐标 X", x_a)
                self.measurement_append_result("■ 起点坐标 Y", y_a)
                self.measurement_append_result("■ 方位角", angle, "°")
                self.measurement_append_result("■ 计算距离", d_ab, "m")
                self.measurement_append_result("■ 终点坐标 X", x_b)
                self.measurement_append_result("■ 终点坐标 Y", y_b)

            elif self.current_measurement_operation == 4:# 坐标反算
                x1 = self.measurement_get_single_value(0)
                y1 = self.measurement_get_single_value(1)
                x2 = self.measurement_get_single_value(2)
                y2 = self.measurement_get_single_value(3)
                x3 = self.measurement_get_single_value(4)
                y3 = self.measurement_get_single_value(5)

                # 计算方位角和距离
                azimuth12 = self.calculate_azimuth(x1, y1, x2, y2)
                distance12 = math.hypot(x2-x1, y2-y1)

                azimuth23 = self.calculate_azimuth(x2, y2, x3, y3)
                distance23 = math.hypot(x3-x2, y3-y2)

                # 计算夹角
                angle = self.calculate_included_angle(x1, y1, x2, y2, x3, y3)

                self.measurement_append_result("■ 点1坐标 X", x1)
                self.measurement_append_result("■ 点1坐标 Y", y1)
                self.measurement_append_result("■ 点2坐标 X", x2)
                self.measurement_append_result("■ 点2坐标 Y", y2)
                self.measurement_append_result("■ 点3坐标 X", x3)
                self.measurement_append_result("■ 点3坐标 Y", y3)
                self.measurement_append_result("■ 1→2方位角", azimuth12, "°")
                self.measurement_append_result("■ 1→2距离", distance12, "m")
                self.measurement_append_result("■ 2→3方位角", azimuth23, "°")
                self.measurement_append_result("■ 2→3距离", distance23, "m")
                if angle is not None:
                  self.measurement_append_result("■ 夹角(点2处)", angle, "°")

            elif self.current_measurement_operation == 5:# 计算2c值
                left_reading = self.measurement_get_dms_value(0)
                right_reading = self.measurement_get_dms_value(3)

                c_decimal = self.calculate_2c(left_reading, right_reading)
                self.measurement_append_result("■ 盘左读数", left_reading, "°")
                self.measurement_append_result("■ 盘右读数", right_reading, "°")
                self.measurement_append_result("■ 2c值", c_decimal, "°")

            self.status_var.set(f"计算完成 | {self.get_measurement_operation_name()}")

      except ValueError as e:
            messagebox.showerror("输入错误", str(e))
            self.status_var.set(f"输入错误 | {str(e)}")
      except Exception as e:
            messagebox.showerror("计算错误", f"发生意外错误: {str(e)}")
            self.status_var.set(f"错误 | {str(e)}")

    def calculate_azimuth(self, x1, y1, x2, y2):
      """计算两点之间的方位角"""
      dx = x2 - x1
      dy = y2 - y1
      azimuth = math.atan2(dy, dx) * (180 / math.pi)
      if azimuth < 0:
            azimuth += 360
      return azimuth

    def calculate_included_angle(self, x1, y1, x2, y2, x3, y3):
      """计算三点之间的夹角(点2处)"""
      # 向量BA
      ba_x = x1 - x2
      ba_y = y1 - y2
      # 向量BC
      bc_x = x3 - x2
      bc_y = y3 - y2

      # 计算点积和模
      dot_product = ba_x * bc_x + ba_y * bc_y
      mag_ba = math.hypot(ba_x, ba_y)
      mag_bc = math.hypot(bc_x, bc_y)

      if mag_ba == 0 or mag_bc == 0:
            return None

      # 计算夹角(弧度)
      cos_theta = dot_product / (mag_ba * mag_bc)
      cos_theta = max(-1.0, min(1.0, cos_theta))# 确保在有效范围内
      angle_rad = math.acos(cos_theta)

      # 转换为度
      return math.degrees(angle_rad)

    def calculate_2c(self, left_reading, right_reading):
      """计算方向观测法水平角的2c值"""
      left_reading = left_reading % 360
      right_reading = right_reading % 360

      if right_reading >= 180:
            c = left_reading - (right_reading - 180)
      else:
            c = left_reading - (right_reading + 180)
      return c

    def measurement_append_result(self, label, value, unit=""):
      """将结果添加到结果文本框,智能格式化"""
      # 基本格式化
      if isinstance(value, (float, int)):
            # 判断是否为角度值
            is_angle = any(keyword in label for keyword in ["角", "方位", "指标", "2c", "读数"])

            if is_angle:
                # 角度值显示十进制和度分秒
                value_str = f"{value:.4f}"
                d, m, s = self.decimal_to_dms(value)
                dms_str = f"{abs(d)}° {m}' {s}\""
                if d < 0:
                  dms_str = f"-{dms_str}"
                value_str += f"({dms_str})"
            else:
                # 普通数值格式化
                if abs(value) < 0.001 and value != 0:
                  value_str = f"{value:.4e}"
                elif abs(value) >= 10000:
                  value_str = f"{value:,.4f}"
                else:
                  value_str = f"{value:.4f}"
      else:
            value_str = str(value)

      # 添加单位
      if unit:
            value_str += f" {unit}"

      # 添加到结果框
      self.measurement_result_text.insert(tk.END, f"{label: <18}: {value_str}\n")

    def measurement_clear_all(self):
      """清空所有输入字段和结果"""
      self.measurement_clear_inputs()
      self.measurement_clear_result()
      self.status_var.set("已清空 | 选择计算类型并输入参数")

    def measurement_clear_inputs(self):
      """清空所有输入字段"""
      for widget in self.measurement_input_frame.winfo_children():
            if isinstance(widget, ttk.Entry):
                widget.delete(0, tk.END)
            elif isinstance(widget, ttk.Frame):
                for child in widget.winfo_children():
                  if isinstance(child, ttk.Entry):
                        child.delete(0, tk.END)

    def measurement_clear_result(self):
      """清空结果文本框"""
      self.measurement_result_text.delete(1.0, tk.END)
      self.measurement_result_text.insert(tk.END, "【计算结果】\n" + "="*40 + "\n")

    def create_geometry_calculator_tab(self):
      """创建几何计算工具标签页"""
      tab = ttk.Frame(self.notebook)
      self.notebook.add(tab, text="几何计算")

      # 操作选择区域
      self.geometry_operation_frame = ttk.LabelFrame(
            tab,
            text="选择计算类型",
            padding="10"
      )
      self.geometry_operation_frame.pack(fill=tk.X, pady=(0, 10))

      self.geometry_operation_var = tk.IntVar(value=1)

      operations = [
            ("1. 度分秒转十进制", 1),
            ("2. 十进制转度分秒", 2),
            ("3. 圆弧弧长", 3),
            ("4. 扇形面积", 4),
            ("5. 弓形面积", 5),
            ("6. 圆面积", 6),
            ("7. 圆周长", 7),
            ("8. 三角形面积", 8),
            ("9. 三角函数", 9)
      ]

      # 分两行显示单选按钮
      for i, (text, val) in enumerate(operations[:5]):
            rb = ttk.Radiobutton(
                self.geometry_operation_frame,
                text=text,
                variable=self.geometry_operation_var,
                value=val,
                command=self.geometry_operation_changed
            )
            rb.grid(row=0, column=i, padx=5, sticky="w")

      for i, (text, val) in enumerate(operations):
            rb = ttk.Radiobutton(
                self.geometry_operation_frame,
                text=text,
                variable=self.geometry_operation_var,
                value=val,
                command=self.geometry_operation_changed
            )
            rb.grid(row=1, column=i, padx=5, sticky="w")

      # 输入区域
      self.geometry_input_frame = ttk.LabelFrame(
            tab,
            text="输入参数",
            padding="10"
      )
      self.geometry_input_frame.pack(fill=tk.BOTH, expand=True, pady=5)

      # 结果区域
      self.geometry_result_frame = ttk.LabelFrame(
            tab,
            text="计算结果",
            padding="10"
      )
      self.geometry_result_frame.pack(fill=tk.BOTH, expand=True, pady=5)

      self.geometry_result_text = scrolledtext.ScrolledText(
            self.geometry_result_frame,
            width=55,
            height=10,
            font=('Consolas', 10),
            wrap=tk.WORD,
            bg='#f9f9f9',
            relief=tk.SOLID,
            borderwidth=1
      )
      self.geometry_result_text.pack(fill=tk.BOTH, expand=True)
      self.geometry_result_text.insert(tk.END, "【计算结果】\n" + "="*40 + "\n")

      # 按钮区域
      self.geometry_button_frame = ttk.Frame(tab)
      self.geometry_button_frame.pack(pady=(10, 0))

      self.geometry_calculate_btn = ttk.Button(
            self.geometry_button_frame,
            text="计算",
            command=self.geometry_calculate
      )
      self.geometry_calculate_btn.pack(side=tk.LEFT, padx=5)

      self.geometry_clear_btn = ttk.Button(
            self.geometry_button_frame,
            text="清空",
            command=self.geometry_clear_all
      )
      self.geometry_clear_btn.pack(side=tk.LEFT, padx=5)

      # 默认显示第一个操作的输入字段
      self.current_geometry_operation = 1
      self.create_geometry_input_fields()

    def geometry_operation_changed(self):
      """几何计算类型改变时更新输入字段"""
      new_operation = self.geometry_operation_var.get()
      if new_operation != self.current_geometry_operation:
            self.current_geometry_operation = new_operation
            self.create_geometry_input_fields()
            self.geometry_clear_result()
            self.status_var.set(f"已选择: {self.get_geometry_operation_name()} | 请输入参数")

    def get_geometry_operation_name(self):
      """获取当前几何操作名称"""
      names = {
            1: "度分秒转十进制",
            2: "十进制转度分秒",
            3: "圆弧弧长计算",
            4: "扇形面积计算",
            5: "弓形面积计算",
            6: "圆面积计算",
            7: "圆周长计算",
            8: "三角形面积计算",
            9: "三角函数计算"
      }
      return names.get(self.current_geometry_operation, "")

    def create_geometry_input_fields(self):
      """根据当前几何操作创建输入字段"""
      # 清除旧的输入字段
      for widget in self.geometry_input_frame.winfo_children():
            widget.destroy()

      # 创建新的输入字段
      if self.current_geometry_operation == 1:# 度分秒转十进制
            self.create_geometry_dms_input("角度值", 0)

      elif self.current_geometry_operation == 2:# 十进制转度分秒
            self.create_geometry_single_input("十进制角度", 0)

      elif self.current_geometry_operation == 3:# 圆弧弧长
            self.create_geometry_single_input("半径 (m)", 0)
            self.create_geometry_single_input("角度 (度)", 1)

      elif self.current_geometry_operation == 4:# 扇形面积
            self.create_geometry_single_input("半径 (m)", 0)
            self.create_geometry_single_input("角度 (度)", 1)

      elif self.current_geometry_operation == 5:# 弓形面积
            self.create_geometry_single_input("半径 (m)", 0)
            self.create_geometry_single_input("角度 (度)", 1)

      elif self.current_geometry_operation == 6:# 圆面积
            self.create_geometry_single_input("半径 (m)", 0)

      elif self.current_geometry_operation == 7:# 圆周长
            self.create_geometry_single_input("半径 (m)", 0)

      elif self.current_geometry_operation == 8:# 三角形面积
            self.create_geometry_single_input("边长 a (m)", 0)
            self.create_geometry_single_input("边长 b (m)", 1)
            self.create_geometry_single_input("边长 c (m)", 2)

      elif self.current_geometry_operation == 9:# 三角函数
            self.create_geometry_single_input("角度 (度)", 0)

    def create_geometry_single_input(self, label_text, row):
      """创建单个输入字段"""
      frame = ttk.Frame(self.geometry_input_frame)
      frame.grid(row=row, column=0, sticky="ew", pady=2)

      label = ttk.Label(frame, text=label_text, width=15, anchor="e")
      label.pack(side=tk.LEFT, padx=5)

      entry = ttk.Entry(frame, width=15)
      entry.pack(side=tk.LEFT, fill=tk.X, expand=True)

      # 存储输入框引用
      setattr(self, f"geometry_entry_{row}", entry)

    def create_geometry_dms_input(self, label_text, start_row):
      """创建度分秒输入字段组"""
      frame = ttk.Frame(self.geometry_input_frame)
      frame.grid(row=start_row, column=0, sticky="ew", pady=2)

      # 标签
      label = ttk.Label(frame, text=f"{label_text}:", width=15, anchor="e")
      label.pack(side=tk.LEFT, padx=5)

      # 度
      subframe = ttk.Frame(frame)
      subframe.pack(side=tk.LEFT, fill=tk.X, expand=True)

      ttk.Label(subframe, text="度").pack(side=tk.LEFT)
      entry_deg = ttk.Entry(subframe, width=5)
      entry_deg.pack(side=tk.LEFT, padx=2)

      # 分
      ttk.Label(subframe, text="分").pack(side=tk.LEFT)
      entry_min = ttk.Entry(subframe, width=5)
      entry_min.pack(side=tk.LEFT, padx=2)

      # 秒
      ttk.Label(subframe, text="秒").pack(side=tk.LEFT)
      entry_sec = ttk.Entry(subframe, width=6)
      entry_sec.pack(side=tk.LEFT, padx=2)

      # 存储输入框引用
      setattr(self, f"geometry_entry_{start_row}_deg", entry_deg)
      setattr(self, f"geometry_entry_{start_row}_min", entry_min)
      setattr(self, f"geometry_entry_{start_row}_sec", entry_sec)

    def geometry_get_dms_value(self, base_name):
      """获取度分秒值并转换为十进制"""
      try:
            deg = float(getattr(self, f"geometry_entry_{base_name}_deg").get())
            minutes = float(getattr(self, f"geometry_entry_{base_name}_min").get())
            seconds = float(getattr(self, f"geometry_entry_{base_name}_sec").get())
            return self.dms_to_decimal(deg, minutes, seconds)
      except ValueError:
            raise ValueError(f"请输入有效的度分秒数值")

    def geometry_get_single_value(self, entry_name):
      """获取单个输入值"""
      try:
            value = getattr(self, f"geometry_entry_{entry_name}").get()
            if not value:
                raise ValueError("输入不能为空")
            return float(value)
      except ValueError:
            raise ValueError(f"请输入有效的数值")

    def geometry_calculate(self):
      """执行几何计算"""
      try:
            self.geometry_clear_result()
            self.status_var.set("计算中...")
            self.master.update()

            if self.current_geometry_operation == 1:# 度分秒转十进制
                angle_dms = self.geometry_get_dms_value(0)
                self.geometry_append_result("■ 度分秒值",
                                 f"{getattr(self, 'geometry_entry_0_deg').get()}° {getattr(self, 'geometry_entry_0_min').get()}' {getattr(self, 'geometry_entry_0_sec').get()}\"")
                self.geometry_append_result("■ 十进制值", angle_dms, "°")

            elif self.current_geometry_operation == 2:# 十进制转度分秒
                decimal_angle = self.geometry_get_single_value(0)
                d, m, s = self.decimal_to_dms(decimal_angle)
                self.geometry_append_result("■ 十进制值", decimal_angle, "°")
                self.geometry_append_result("■ 度分秒值", f"{d}° {m}' {s}\"")

            elif self.current_geometry_operation == 3:# 圆弧弧长
                radius = self.geometry_get_single_value(0)
                angle = self.geometry_get_single_value(1)
                arc_length = self.calculate_arc_length(radius, angle)
                self.geometry_append_result("■ 半径", radius, "m")
                self.geometry_append_result("■ 角度", angle, "°")
                self.geometry_append_result("■ 弧长", arc_length, "m")

            elif self.current_geometry_operation == 4:# 扇形面积
                radius = self.geometry_get_single_value(0)
                angle = self.geometry_get_single_value(1)
                sector_area = self.calculate_sector_area(radius, angle)
                self.geometry_append_result("■ 半径", radius, "m")
                self.geometry_append_result("■ 角度", angle, "°")
                self.geometry_append_result("■ 扇形面积", sector_area, "m²")

            elif self.current_geometry_operation == 5:# 弓形面积
                radius = self.geometry_get_single_value(0)
                angle = self.geometry_get_single_value(1)
                lune_area = self.calculate_lune_area(radius, angle)
                self.geometry_append_result("■ 半径", radius, "m")
                self.geometry_append_result("■ 角度", angle, "°")
                self.geometry_append_result("■ 弓形面积", lune_area, "m²")

            elif self.current_geometry_operation == 6:# 圆面积
                radius = self.geometry_get_single_value(0)
                area = self.calculate_circle_area(radius)
                self.geometry_append_result("■ 半径", radius, "m")
                self.geometry_append_result("■ 圆面积", area, "m²")

            elif self.current_geometry_operation == 7:# 圆周长
                radius = self.geometry_get_single_value(0)
                circumference = self.calculate_circle_circumference(radius)
                self.geometry_append_result("■ 半径", radius, "m")
                self.geometry_append_result("■ 圆周长", circumference, "m")

            elif self.current_geometry_operation == 8:# 三角形面积
                a = self.geometry_get_single_value(0)
                b = self.geometry_get_single_value(1)
                c = self.geometry_get_single_value(2)
                area = self.calculate_triangle_area(a, b, c)
                self.geometry_append_result("■ 边长 a", a, "m")
                self.geometry_append_result("■ 边长 b", b, "m")
                self.geometry_append_result("■ 边长 c", c, "m")
                self.geometry_append_result("■ 三角形面积", area, "m²")

            elif self.current_geometry_operation == 9:# 三角函数
                angle = self.geometry_get_single_value(0)
                trig_values = self.calculate_trigonometric_functions(angle)
                self.geometry_append_result("■ 角度值", angle, "°")
                self.geometry_result_text.insert(tk.END, "■ 三角函数值:\n")
                for func, value in trig_values.items():
                  if math.isinf(value):
                        self.geometry_result_text.insert(tk.END, f"{func}: 无穷大\n")
                  else:
                        self.geometry_result_text.insert(tk.END, f"{func}: {value:.6f}\n")

            self.status_var.set(f"计算完成 | {self.get_geometry_operation_name()}")

      except ValueError as e:
            messagebox.showerror("输入错误", str(e))
            self.status_var.set(f"输入错误 | {str(e)}")
      except Exception as e:
            messagebox.showerror("计算错误", f"发生意外错误: {str(e)}")
            self.status_var.set(f"错误 | {str(e)}")

    def calculate_arc_length(self, radius, angle_degrees):
      """计算圆弧的弧长"""
      return (angle_degrees / 360) * 2 * math.pi * radius

    def calculate_sector_area(self, radius, angle_degrees):
      """计算圆弧所对的扇形面积"""
      return (angle_degrees / 360) * math.pi * (radius ** 2)

    def calculate_lune_area(self, radius, angle_degrees):
      """计算弓形面积"""
      sector_area = self.calculate_sector_area(radius, angle_degrees)
      if angle_degrees <= 180:
            triangle_area = 0.5 * radius ** 2 * math.sin(math.radians(angle_degrees))
            return sector_area - triangle_area
      else:
            return self.calculate_sector_area(radius, 360) - sector_area

    def calculate_circle_area(self, radius):
      """计算圆的面积"""
      return math.pi * (radius ** 2)

    def calculate_circle_circumference(self, radius):
      """计算圆的周长"""
      return 2 * math.pi * radius

    def calculate_triangle_area(self, a, b, c):
      """使用海伦公式计算三角形的面积"""
      if a + b > c and a + c > b and b + c > a:
            s = (a + b + c) / 2
            area = math.sqrt(s * (s - a) * (s - b) * (s - c))
            return area
      else:
            raise ValueError("输入的边长无法构成三角形")

    def calculate_trigonometric_functions(self, angle_degrees):
      """计算并返回所有基本三角函数值"""
      angle_radians = math.radians(angle_degrees)
      sin_value = math.sin(angle_radians)
      cos_value = math.cos(angle_radians)
      tan_value = math.tan(angle_radians)
      csc_value = 1 / sin_value if sin_value != 0 else float('inf')
      sec_value = 1 / cos_value if cos_value != 0 else float('inf')
      cot_value = 1 / tan_value if tan_value != 0 else float('inf')
      return {
            "sin": sin_value,
            "cos": cos_value,
            "tan": tan_value,
            "csc": csc_value,
            "sec": sec_value,
            "cot": cot_value
      }

    def geometry_append_result(self, label, value, unit=""):
      """将结果添加到结果文本框,智能格式化"""
      # 基本格式化
      if isinstance(value, (float, int)):
            if abs(value) < 0.001 and value != 0:
                value_str = f"{value:.4e}"
            elif abs(value) >= 10000:
                value_str = f"{value:,.4f}"
            else:
                value_str = f"{value:.4f}"
      else:
            value_str = str(value)

      # 添加单位
      if unit:
            value_str += f" {unit}"

      # 添加到结果框
      self.geometry_result_text.insert(tk.END, f"{label: <12}: {value_str}\n")

    def geometry_clear_all(self):
      """清空所有输入字段和结果"""
      self.geometry_clear_inputs()
      self.geometry_clear_result()
      self.status_var.set("已清空 | 选择计算类型并输入参数")

    def geometry_clear_inputs(self):
      """清空所有输入字段"""
      for widget in self.geometry_input_frame.winfo_children():
            if isinstance(widget, ttk.Entry):
                widget.delete(0, tk.END)
            elif isinstance(widget, ttk.Frame):
                for child in widget.winfo_children():
                  if isinstance(child, ttk.Entry):
                        child.delete(0, tk.END)

    def geometry_clear_result(self):
      """清空结果文本框"""
      self.geometry_result_text.delete(1.0, tk.END)
      self.geometry_result_text.insert(tk.END, "【计算结果】\n" + "="*40 + "\n")

    def create_leveling_calculator_tab(self):
      """创建水准测量高程计算工具标签页"""
      tab = ttk.Frame(self.notebook)
      self.notebook.add(tab, text="水准测量")

      # 输入区域
      self.leveling_input_frame = ttk.LabelFrame(
            tab,
            text="水准测量数据录入",
            padding="10"
      )
      self.leveling_input_frame.pack(fill=tk.BOTH, expand=True, pady=5)

      # 创建输入表格
      self.create_leveling_input_table()

      # 数据输入区域
      self.leveling_data_entry_frame = ttk.LabelFrame(
            tab,
            text="当前测站数据输入",
            padding="10"
      )
      self.leveling_data_entry_frame.pack(fill=tk.X, pady=5)

      self.create_leveling_data_entry_fields()

      # 按钮区域
      self.leveling_button_frame = ttk.Frame(tab)
      self.leveling_button_frame.pack(pady=(10, 0))

      self.leveling_add_btn = ttk.Button(
            self.leveling_button_frame,
            text="添加/更新测站",
            command=self.leveling_add_data_from_entry
      )
      self.leveling_add_btn.pack(side=tk.LEFT, padx=5)

      self.leveling_calculate_btn = ttk.Button(
            self.leveling_button_frame,
            text="计算高程",
            command=self.leveling_calculate_elevations
      )
      self.leveling_calculate_btn.pack(side=tk.LEFT, padx=5)

      self.leveling_clear_btn = ttk.Button(
            self.leveling_button_frame,
            text="清空所有数据",
            command=self.leveling_clear_all
      )
      self.leveling_clear_btn.pack(side=tk.LEFT, padx=5)

      self.leveling_copy_btn = ttk.Button(
            self.leveling_button_frame,
            text="复制数据",
            command=self.leveling_copy_data_to_clipboard
      )
      self.leveling_copy_btn.pack(side=tk.LEFT, padx=5)

      # 存储当前选中的行
      self.current_leveling_selected = None

    def create_leveling_input_table(self):
      """创建水准测量输入表格框架"""
      headers = ["测站", "后视读数(m)", "前视读数(m)", "高程(m)", "距离(m)", "备注"]
      self.leveling_tree = ttk.Treeview(
            self.leveling_input_frame,
            columns=headers,
            show="headings",
            height=10
      )

      col_widths =
      for header, width in zip(headers, col_widths):
            self.leveling_tree.heading(header, text=header)
            self.leveling_tree.column(header, width=width, anchor=tk.CENTER)

      vsb = ttk.Scrollbar(
            self.leveling_input_frame,
            orient="vertical",
            command=self.leveling_tree.yview
      )
      self.leveling_tree.configure(yscrollcommand=vsb.set)
      self.leveling_tree.bind('<<TreeviewSelect>>', self.on_leveling_tree_select)

      self.leveling_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
      vsb.pack(side=tk.RIGHT, fill=tk.Y)

    def create_leveling_data_entry_fields(self):
      """创建水准测量数据输入字段"""
      ttk.Label(self.leveling_data_entry_frame, text="测站名称:").grid(row=0, column=0, padx=5, pady=2, sticky="e")
      self.leveling_station_entry = ttk.Entry(self.leveling_data_entry_frame, width=15)
      self.leveling_station_entry.grid(row=0, column=1, padx=5, pady=2, sticky="w")

      ttk.Label(self.leveling_data_entry_frame, text="后视读数(m):").grid(row=1, column=0, padx=5, pady=2, sticky="e")
      self.leveling_back_sight_entry = ttk.Entry(self.leveling_data_entry_frame, width=15)
      self.leveling_back_sight_entry.grid(row=1, column=1, padx=5, pady=2, sticky="w")

      ttk.Label(self.leveling_data_entry_frame, text="前视读数(m):").grid(row=2, column=0, padx=5, pady=2, sticky="e")
      self.leveling_fore_sight_entry = ttk.Entry(self.leveling_data_entry_frame, width=15)
      self.leveling_fore_sight_entry.grid(row=2, column=1, padx=5, pady=2, sticky="w")

      ttk.Label(self.leveling_data_entry_frame, text="高程(m):").grid(row=0, column=2, padx=5, pady=2, sticky="e")
      self.leveling_elevation_entry = ttk.Entry(self.leveling_data_entry_frame, width=15)
      self.leveling_elevation_entry.grid(row=0, column=3, padx=5, pady=2, sticky="w")

      ttk.Label(self.leveling_data_entry_frame, text="距离(m):").grid(row=1, column=2, padx=5, pady=2, sticky="e")
      self.leveling_distance_entry = ttk.Entry(self.leveling_data_entry_frame, width=15)
      self.leveling_distance_entry.grid(row=1, column=3, padx=5, pady=2, sticky="w")

      ttk.Label(self.leveling_data_entry_frame, text="备注:").grid(row=2, column=2, padx=5, pady=2, sticky="e")
      self.leveling_remark_entry = ttk.Entry(self.leveling_data_entry_frame, width=15)
      self.leveling_remark_entry.grid(row=2, column=3, padx=5, pady=2, sticky="w")

      self.leveling_station_entry.focus_set()

    def leveling_add_data_from_entry(self):
      """从输入字段添加水准测量数据"""
      try:
            station = self.leveling_station_entry.get().strip()
            if not station:
                raise ValueError("测站名称不能为空")

            back_sight = self.validate_float_input(self.leveling_back_sight_entry.get().strip(), "后视读数")
            fore_sight = self.validate_float_input(self.leveling_fore_sight_entry.get().strip(), "前视读数")
            elevation = self.validate_float_input(self.leveling_elevation_entry.get().strip(), "高程")
            distance = self.validate_float_input(self.leveling_distance_entry.get().strip(), "距离")
            remark = self.leveling_remark_entry.get().strip()

            values = (
                station,
                f"{back_sight:.3f}" if back_sight is not None else "",
                f"{fore_sight:.3f}" if fore_sight is not None else "",
                f"{elevation:.3f}" if elevation is not None else "",
                f"{distance:.1f}" if distance is not None else "",
                remark
            )

            if self.current_leveling_selected and self.leveling_tree.exists(self.current_leveling_selected):
                self.leveling_tree.item(self.current_leveling_selected, values=values)
                message = f"已更新测站 {station} 的数据"
            else:
                new_id = str(uuid.uuid4())
                self.leveling_tree.insert("", tk.END, values=values, iid=new_id)
                message = f"已添加测站 {station} 的数据"

            self.status_var.set(message)
            self.leveling_clear_entry_fields()
            self.leveling_station_entry.focus_set()

      except ValueError as e:
            messagebox.showerror("输入错误", str(e))
            self.status_var.set(f"输入错误 | {str(e)}")
      except Exception as e:
            messagebox.showerror("错误", f"操作数据时出错: {str(e)}")
            self.status_var.set(f"错误 | {str(e)}")

    def on_leveling_tree_select(self, event):
      """当选择水准测量表格行时,加载数据到输入字段"""
      selected = self.leveling_tree.selection()
      if selected and self.leveling_tree.exists(selected):
            self.current_leveling_selected = selected
            values = self.leveling_tree.item(self.current_leveling_selected)['values']

            self.leveling_clear_entry_fields()

            if values:
                self.leveling_station_entry.insert(0, values)

                if len(values) > 1 and values:
                  self.leveling_back_sight_entry.insert(0, values)

                if len(values) > 2 and values:
                  self.leveling_fore_sight_entry.insert(0, values)

                if len(values) > 3 and values:
                  self.leveling_elevation_entry.insert(0, values)

                if len(values) > 4 and values:
                  self.leveling_distance_entry.insert(0, values)

                if len(values) > 5 and values:
                  self.leveling_remark_entry.insert(0, values)

            self.status_var.set(f"已选择测站 {values} 进行编辑")

    def leveling_clear_entry_fields(self):
      """清空水准测量输入字段"""
      self.current_leveling_selected = None
      for entry in [self.leveling_station_entry, self.leveling_back_sight_entry,
                     self.leveling_fore_sight_entry, self.leveling_elevation_entry,
                     self.leveling_distance_entry, self.leveling_remark_entry]:
            entry.delete(0, tk.END)

    def leveling_get_input_data(self):
      """获取所有水准测量输入数据"""
      data = []
      for item in self.leveling_tree.get_children():
            if not self.leveling_tree.exists(item):
                continue

            values = self.leveling_tree.item(item)['values']
            if not values:
                continue

            station = values

            try:
                back_sight = float(values) if len(values) > 1 and values else None
                fore_sight = float(values) if len(values) > 2 and values else None
                elevation = float(values) if len(values) > 3 and values else None
                remark = values if len(values) > 5 else ""

                data.append({
                  'station': station,
                  'back_sight': back_sight,
                  'fore_sight': fore_sight,
                  'elevation': elevation,
                  'remark': remark
                })
            except ValueError:
                continue

      return data

    def leveling_calculate_elevations(self):
      """计算各测站高程"""
      try:
            self.status_var.set("正在计算高程...")
            self.master.update()

            data = self.leveling_get_input_data()

            if len(data) < 2:
                raise ValueError("至少需要两个测站的数据才能进行计算")

            if data['elevation'] is None:
                raise ValueError("第一个测站必须输入起始高程")

            if data['back_sight'] is None:
                raise ValueError("第一个测站必须输入后视读数")

            start_elevation = data['elevation']

            # 更新第一个测站的高程显示
            if len(self.leveling_tree.get_children()) > 0:
                first_item = self.leveling_tree.get_children()
                values = list(self.leveling_tree.item(first_item)['values'])
                if len(values) > 3:
                  values = f"{start_elevation:.3f}"
                  self.leveling_tree.item(first_item, values=values)

            # 计算中间点高程
            for i in range(1, len(data)-1):
                prev_data = data
                current = data

                if prev_data['back_sight'] is None:
                  raise ValueError(f"测站 {prev_data['station']} 缺少后视读数")

                if current['fore_sight'] is None:
                  raise ValueError(f"测站 {current['station']} 缺少前视读数")

                # 计算高差和高程
                elevation_change = prev_data['back_sight'] - current['fore_sight']
                current_elevation = prev_data['elevation'] + elevation_change

                # 更新当前测站的高程
                if i < len(self.leveling_tree.get_children()):
                  item_id = self.leveling_tree.get_children()
                  if self.leveling_tree.exists(item_id):
                        current_values = list(self.leveling_tree.item(item_id)['values'])
                        if len(current_values) > 3:
                            current_values = f"{current_elevation:.3f}"
                            self.leveling_tree.item(item_id, values=current_values)

            # 处理最后一个测站
            last_data = data[-1]
            if len(data) > 1:
                prev_data = data[-2]
                if prev_data['back_sight'] is None:
                  raise ValueError(f"测站 {prev_data['station']} 缺少后视读数")

                if last_data['fore_sight'] is None:
                  raise ValueError(f"测站 {last_data['station']} 缺少前视读数")

                # 计算最后一个测站的高程
                elevation_change = prev_data['back_sight'] - last_data['fore_sight']
                last_elevation = prev_data['elevation'] + elevation_change

                # 更新最后一个测站的高程
                if len(self.leveling_tree.get_children()) > len(data)-1:
                  item_id = self.leveling_tree.get_children()
                  if self.leveling_tree.exists(item_id):
                        last_values = list(self.leveling_tree.item(item_id)['values'])
                        if len(last_values) > 3:
                            last_values = f"{last_elevation:.3f}"
                            self.leveling_tree.item(item_id, values=last_values)

            self.status_var.set("高程计算完成")
            messagebox.showinfo("计算完成", "高程计算已完成,结果已更新到表格中")

      except ValueError as e:
            messagebox.showerror("计算错误", str(e))
            self.status_var.set(f"计算错误 | {str(e)}")
      except Exception as e:
            messagebox.showerror("错误", f"计算高程时出错: {str(e)}")
            self.status_var.set(f"错误 | {str(e)}")

    def leveling_clear_all(self):
      """清空所有水准测量数据"""
      for item in self.leveling_tree.get_children():
            self.leveling_tree.delete(item)
      self.leveling_clear_entry_fields()
      self.status_var.set("已清空所有数据")

    def leveling_copy_data_to_clipboard(self):
      """将水准测量表格数据复制到剪贴板"""
      try:
            # 获取表头
            headers = for col in self.leveling_tree['columns']]
            # 只保留需要的列:测站、后视读数、前视读数、高程、备注
            keep_columns = # 对应索引
            headers = for i in keep_columns]

            # 获取所有行数据
            rows = []
            for item in self.leveling_tree.get_children():
                values = self.leveling_tree.item(item)['values']
                if values:
                  # 只保留需要的列
                  row = if i < len(values) else "" for i in keep_columns]
                  rows.append("\t".join(str(x) for x in row))

            if not rows:
                messagebox.showwarning("复制警告", "没有数据可复制")
                self.status_var.set("复制警告 | 没有数据可复制")
                return

            # 构建剪贴板内容
            clipboard_content = "\t".join(headers) + "\n" + "\n".join(rows)

            # 复制到剪贴板
            self.master.clipboard_clear()
            self.master.clipboard_append(clipboard_content)

            self.status_var.set("数据已复制到剪贴板")
            messagebox.showinfo("复制成功", "表格数据已复制到剪贴板,可以粘贴到Excel或其他程序中")

      except Exception as e:
            messagebox.showerror("复制错误", f"复制数据时出错: {str(e)}")
            self.status_var.set(f"复制错误 | {str(e)}")

    def create_area_converter_tab(self):
      """创建面积单位转换工具标签页"""
      tab = ttk.Frame(self.notebook)
      self.notebook.add(tab, text="面积转换")

      # 操作选择区域
      self.area_conversion_frame = ttk.LabelFrame(
            tab,
            text="选择转换类型",
            padding="10"
      )
      self.area_conversion_frame.pack(fill=tk.X, pady=(0, 10))

      self.area_conversion_var = tk.IntVar(value=1)

      conversions = [
            ("平方米 → 亩", 1),
            ("亩 → 平方米", 2)
      ]

      for i, (text, val) in enumerate(conversions):
            rb = ttk.Radiobutton(
                self.area_conversion_frame,
                text=text,
                variable=self.area_conversion_var,
                value=val,
                command=self.area_conversion_changed
            )
            rb.grid(row=0, column=i, padx=10, sticky="w")

      # 输入区域
      self.area_input_frame = ttk.LabelFrame(
            tab,
            text="输入参数",
            padding="10"
      )
      self.area_input_frame.pack(fill=tk.X, pady=5)

      # 结果区域
      self.area_result_frame = ttk.LabelFrame(
            tab,
            text="转换结果",
            padding="10"
      )
      self.area_result_frame.pack(fill=tk.BOTH, expand=True, pady=5)

      self.area_result_var = tk.StringVar()
      self.area_result_display = tk.Text(
            self.area_result_frame,
            font=('微软雅黑', 12),
            bg='white',
            relief=tk.SUNKEN,
            padx=10,
            pady=10,
            wrap=tk.WORD,
            height=3,
            state='disabled'# 初始设置为不可编辑
      )
      self.area_result_display.pack(fill=tk.BOTH, expand=True)

      # 添加右键菜单用于复制
      self.area_context_menu = Menu(self.area_result_display, tearoff=0)
      self.area_context_menu.add_command(label="复制", command=self.area_copy_result)
      self.area_result_display.bind("<Button-3>", self.area_show_context_menu)

      # 按钮区域
      self.area_button_frame = ttk.Frame(tab)
      self.area_button_frame.pack(pady=(10, 0))

      self.area_calculate_btn = ttk.Button(
            self.area_button_frame,
            text="计算",
            command=self.area_convert_units,
            width=10
      )
      self.area_calculate_btn.pack(side=tk.LEFT, padx=5)

      self.area_copy_btn = ttk.Button(
            self.area_button_frame,
            text="复制结果",
            command=self.area_copy_result,
            width=10
      )
      self.area_copy_btn.pack(side=tk.LEFT, padx=5)

      self.area_clear_btn = ttk.Button(
            self.area_button_frame,
            text="清空",
            command=self.area_clear_all,
            width=10
      )
      self.area_clear_btn.pack(side=tk.LEFT, padx=5)

      # 默认显示第一个转换类型的输入字段
      self.current_area_conversion = 1
      self.create_area_input_field()

      # 绑定回车键计算
      self.master.bind('<Return>', lambda event: self.area_convert_units())

    def area_show_context_menu(self, event):
      """显示面积转换右键菜单"""
      try:
            self.area_context_menu.tk_popup(event.x_root, event.y_root)
      finally:
            self.area_context_menu.grab_release()

    def area_copy_result(self):
      """复制面积转换结果到剪贴板"""
      result = self.area_result_display.get("1.0", "end-1c")
      if result.strip():
            self.master.clipboard_clear()
            self.master.clipboard_append(result)
            messagebox.showinfo("复制成功", "结果已复制到剪贴板")

    def area_conversion_changed(self):
      """面积转换类型改变时更新界面"""
      new_conversion = self.area_conversion_var.get()
      if new_conversion != self.current_area_conversion:
            self.current_area_conversion = new_conversion
            self.create_area_input_field()
            self.area_clear_result()

    def create_area_input_field(self):
      """创建面积转换输入字段"""
      # 清除旧的输入字段
      for widget in self.area_input_frame.winfo_children():
            widget.destroy()

      # 创建新的输入字段
      if self.current_area_conversion == 1:# 平方米转亩
            label_text = "平方米 (m²):"
      else:# 亩转平方米
            label_text = "亩:"

      frame = ttk.Frame(self.area_input_frame)
      frame.pack(fill=tk.X)

      label = ttk.Label(frame, text=label_text, width=12)
      label.pack(side=tk.LEFT, padx=5)

      self.area_entry = ttk.Entry(frame)
      self.area_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
      self.area_entry.focus()

    def square_meters_to_mu(self, square_meters):
      """将平方米转换为亩 (1亩≈666.67平方米)"""
      return square_meters / 666.67

    def mu_to_square_meters(self, mu):
      """将亩转换为平方米 (1亩≈666.67平方米)"""
      return mu * 666.67

    def area_convert_units(self):
      """执行面积单位转换"""
      try:
            input_value = float(self.area_entry.get())
            if input_value < 0:
                raise ValueError("输入值不能为负数")

            if self.current_area_conversion == 1:# 平方米转亩
                result = self.square_meters_to_mu(input_value)
                result_str = f"{input_value:,.2f} 平方米 = {result:,.4f} 亩"
            else:# 亩转平方米
                result = self.mu_to_square_meters(input_value)
                result_str = f"{input_value:,.2f} 亩 = {result:,.2f} 平方米"

            # 更新结果显示
            self.area_result_display.config(state='normal')
            self.area_result_display.delete("1.0", tk.END)
            self.area_result_display.insert(tk.END, result_str)
            self.area_result_display.config(state='disabled')

      except ValueError as e:
            messagebox.showerror("输入错误", "请输入有效的正数!")
      except Exception as e:
            messagebox.showerror("转换错误", f"发生意外错误: {str(e)}")

    def area_clear_all(self):
      """清空所有面积转换输入和结果"""
      self.area_entry.delete(0, tk.END)
      self.area_clear_result()

    def area_clear_result(self):
      """清空面积转换结果显示"""
      self.area_result_display.config(state='normal')
      self.area_result_display.delete("1.0", tk.END)
      self.area_result_display.config(state='disabled')

    @staticmethod
    def dms_to_decimal(degrees, minutes, seconds):
      """将度分秒转换为十进制度数"""
      sign = 1 if degrees >= 0 else -1
      return degrees + sign * minutes / 60 + sign * seconds / 3600

    @staticmethod
    def decimal_to_dms(decimal_angle):
      """将十进制度数转换为度分秒"""
      sign = 1 if decimal_angle >= 0 else -1
      decimal_angle = abs(decimal_angle)

      degrees = int(decimal_angle)
      remaining = (decimal_angle - degrees) * 60
      minutes = int(remaining)
      seconds = round((remaining - minutes) * 60, 1)

      # 处理60秒进位
      if seconds >= 60:
            seconds -= 60
            minutes += 1
      if minutes >= 60:
            minutes -= 60
            degrees += 1

      return sign * degrees, minutes, seconds

    @staticmethod
    def validate_float_input(value_str, field_name):
      """验证浮点输入"""
      if not value_str:
            return None
      try:
            return float(value_str)
      except ValueError:
            raise ValueError(f"{field_name}必须是有效的数字")

if __name__ == "__main__":
    root = tk.Tk()
    app = MultiToolApplication(root)
    root.mainloop()


cjf160204 发表于 3 天前

成品如下,可以直接运行

cjf160204 发表于 前天 08:09

python            

zgs378530220 发表于 前天 00:50

这个是vb系列的代码么,感觉像VBA又不太像

神枪手 发表于 3 天前

新帖,支持下

张向华 发表于 前天 00:08

支持原创,谢谢分享

zgs378530220 发表于 前天 00:49

首先支持原创,谢谢分享。

lxl217114 发表于 前天 09:28


支持原创,谢谢分享

czb203 发表于 前天 14:59

支持原创,谢谢分享

paulpipi 发表于 前天 15:28

虽然不常用,但感谢楼主分享
页: [1] 2
查看完整版本: 测量计算工具