明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 234|回复: 9

测量计算工具

  [复制链接]
发表于 前天 20:06 | 显示全部楼层 |阅读模式
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[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=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&#178;")

            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&#178;")

            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&#178;")

            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&#178;")

            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 = [80, 90, 90, 90, 80, 150]
        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[0]):
            self.current_leveling_selected = selected[0]
            values = self.leveling_tree.item(self.current_leveling_selected)['values']

            self.leveling_clear_entry_fields()

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

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

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

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

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

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

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

    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[0]

            try:
                back_sight = float(values[1]) if len(values) > 1 and values[1] else None
                fore_sight = float(values[2]) if len(values) > 2 and values[2] else None
                elevation = float(values[3]) if len(values) > 3 and values[3] else None
                remark = values[5] 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[0]['elevation'] is None:
                raise ValueError("第一个测站必须输入起始高程")

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

            start_elevation = data[0]['elevation']

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

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

                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()[i]
                    if self.leveling_tree.exists(item_id):
                        current_values = list(self.leveling_tree.item(item_id)['values'])
                        if len(current_values) > 3:
                            current_values[3] = 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()[len(data)-1]
                    if self.leveling_tree.exists(item_id):
                        last_values = list(self.leveling_tree.item(item_id)['values'])
                        if len(last_values) > 3:
                            last_values[3] = 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 = [self.leveling_tree.heading(col)['text'] for col in self.leveling_tree['columns']]
            # 只保留需要的列:测站、后视读数、前视读数、高程、备注
            keep_columns = [0, 1, 2, 3, 5]  # 对应索引
            headers = [headers[i] for i in keep_columns]

            # 获取所有行数据
            rows = []
            for item in self.leveling_tree.get_children():
                values = self.leveling_tree.item(item)['values']
                if values:
                    # 只保留需要的列
                    row = [values[i] 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&#178;):"
        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()


回复

使用道具 举报

 楼主| 发表于 前天 20:09 | 显示全部楼层
成品如下,可以直接运行

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
回复 支持 1 反对 0

使用道具 举报

发表于 前天 20:19 | 显示全部楼层
新帖,支持下
回复 支持 反对

使用道具 举报

发表于 昨天 00:08 | 显示全部楼层
支持原创,谢谢分享
回复 支持 反对

使用道具 举报

发表于 昨天 00:49 来自手机 | 显示全部楼层
首先支持原创,谢谢分享。
回复 支持 反对

使用道具 举报

发表于 昨天 00:50 来自手机 | 显示全部楼层
这个是vb系列的代码么,感觉像VBA又不太像
回复 支持 反对

使用道具 举报

 楼主| 发表于 昨天 08:09 | 显示全部楼层
python            
回复 支持 反对

使用道具 举报

发表于 昨天 09:28 | 显示全部楼层

支持原创,谢谢分享
回复 支持 反对

使用道具 举报

发表于 昨天 14:59 | 显示全部楼层
支持原创,谢谢分享
回复 支持 反对

使用道具 举报

发表于 昨天 15:28 来自手机 | 显示全部楼层
虽然不常用,但感谢楼主分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-4-29 00:54 , Processed in 0.247605 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表