- 积分
- 4888
- 明经币
- 个
- 注册时间
- 2022-9-23
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
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²")
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 = [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²):"
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()
|
|