Python编写一个功能完整的单位转换工具

Python单位转换工具

下面是一个功能完整的单位转换工具,使用Python和Tkinter实现图形界面。该工具支持多种物理量的转换,包括长度、质量、温度、速度、面积和体积等。

import tkinter as tk
from tkinter import ttk, messagebox
import math

class UnitConverter:
    def __init__(self, root):
        self.root = root
        self.root.title("多功能单位转换工具")
        self.root.geometry("700x500")
        self.root.resizable(True, True)
        self.root.configure(bg="#f0f8ff")
        
        # 设置主题样式
        self.style = ttk.Style()
        self.style.theme_use("clam")
        self.style.configure("TFrame", background="#f0f8ff")
        self.style.configure("TLabel", background="#f0f8ff", font=("Arial", 10))
        self.style.configure("TButton", font=("Arial", 10, "bold"), background="#4b86b4", foreground="white")
        self.style.configure("TCombobox", font=("Arial", 10))
        self.style.configure("Header.TLabel", font=("Arial", 14, "bold"), foreground="#2a4d69")
        
        # 创建主框架
        self.main_frame = ttk.Frame(root, padding=20)
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title_label = ttk.Label(self.main_frame, text="多功能单位转换工具", style="Header.TLabel")
        title_label.pack(pady=(0, 20))
        
        # 创建转换类别选择
        category_frame = ttk.Frame(self.main_frame)
        category_frame.pack(fill=tk.X, pady=10)
        
        ttk.Label(category_frame, text="转换类别:").pack(side=tk.LEFT, padx=(0, 10))
        
        self.category_var = tk.StringVar()
        categories = ["长度", "质量", "温度", "速度", "面积", "体积"]
        self.category_combo = ttk.Combobox(category_frame, textvariable=self.category_var, 
                                          values=categories, state="readonly", width=15)
        self.category_combo.pack(side=tk.LEFT)
        self.category_combo.current(0)
        self.category_combo.bind("<<ComboboxSelected>>", self.update_units)
        
        # 创建输入框架
        input_frame = ttk.Frame(self.main_frame)
        input_frame.pack(fill=tk.X, pady=10)
        
        # 输入值
        ttk.Label(input_frame, text="输入值:").grid(row=0, column=0, padx=(0, 10), sticky=tk.W)
        self.input_var = tk.StringVar()
        self.input_entry = ttk.Entry(input_frame, textvariable=self.input_var, width=15, font=("Arial", 10))
        self.input_entry.grid(row=0, column=1, sticky=tk.W)
        
        # 输入单位
        ttk.Label(input_frame, text="从:").grid(row=0, column=2, padx=(10, 10))
        self.from_unit_var = tk.StringVar()
        self.from_unit_combo = ttk.Combobox(input_frame, textvariable=self.from_unit_var, 
                                           state="readonly", width=15)
        self.from_unit_combo.grid(row=0, column=3, sticky=tk.W)
        
        # 输出单位
        ttk.Label(input_frame, text="到:").grid(row=0, column=4, padx=(10, 10))
        self.to_unit_var = tk.StringVar()
        self.to_unit_combo = ttk.Combobox(input_frame, textvariable=self.to_unit_var, 
                                         state="readonly", width=15)
        self.to_unit_combo.grid(row=0, column=5, sticky=tk.W)
        
        # 转换按钮
        convert_button = ttk.Button(input_frame, text="转换", command=self.convert)
        convert_button.grid(row=0, column=6, padx=(20, 0))
        
        # 创建输出框架
        output_frame = ttk.Frame(self.main_frame)
        output_frame.pack(fill=tk.X, pady=20)
        
        ttk.Label(output_frame, text="结果:").pack(side=tk.LEFT, anchor=tk.N, padx=(0, 10))
        
        self.result_text = tk.Text(output_frame, height=6, width=50, font=("Arial", 10), 
                                 bg="white", relief=tk.SUNKEN, padx=10, pady=10)
        self.result_text.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
        self.result_text.config(state=tk.DISABLED)
        
        # 创建历史记录框架
        history_frame = ttk.LabelFrame(self.main_frame, text="转换历史", padding=10)
        history_frame.pack(fill=tk.BOTH, expand=True, pady=10)
        
        # 历史记录列表
        self.history_listbox = tk.Listbox(history_frame, font=("Arial", 9), bg="white", 
                                        relief=tk.SUNKEN, selectbackground="#d3e0ea")
        self.history_listbox.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 历史记录控制按钮
        button_frame = ttk.Frame(history_frame)
        button_frame.pack(fill=tk.X, pady=(5, 0))
        
        clear_button = ttk.Button(button_frame, text="清除历史", command=self.clear_history)
        clear_button.pack(side=tk.RIGHT)
        
        # 初始化单位
        self.update_units()
        self.conversion_history = []
        
        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("就绪")
        status_bar = ttk.Label(root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)
        
        # 设置初始焦点
        self.input_entry.focus_set()
        
        # 绑定回车键
        self.root.bind("<Return>", lambda event: self.convert())
    
    def update_units(self, event=None):
        """根据选择的类别更新单位列表"""
        category = self.category_var.get()
        
        if category == "长度":
            units = ["米 (m)", "千米 (km)", "厘米 (cm)", "毫米 (mm)", "英寸 (in)", "英尺 (ft)", "码 (yd)", "英里 (mile)"]
        elif category == "质量":
            units = ["克 (g)", "千克 (kg)", "毫克 (mg)", "磅 (lb)", "盎司 (oz)", "吨 (t)"]
        elif category == "温度":
            units = ["摄氏度 (°C)", "华氏度 (°F)", "开尔文 (K)"]
        elif category == "速度":
            units = ["米/秒 (m/s)", "千米/小时 (km/h)", "英里/小时 (mph)", "节 (kn)", "马赫 (Ma)"]
        elif category == "面积":
            units = ["平方米 (m²)", "平方千米 (km²)", "公顷 (ha)", "平方英里 (mi²)", "英亩 (acre)", "平方英尺 (ft²)"]
        elif category == "体积":
            units = ["立方米 (m³)", "升 (L)", "毫升 (mL)", "加仑 (gal)", "立方英尺 (ft³)"]
        else:
            units = []
        
        self.from_unit_combo["values"] = units
        self.to_unit_combo["values"] = units
        
        if units:
            self.from_unit_combo.current(0)
            self.to_unit_combo.current(1)
    
    def convert(self):
        """执行单位转换"""
        # 获取输入值
        try:
            input_value = float(self.input_var.get())
        except ValueError:
            messagebox.showerror("输入错误", "请输入有效的数字")
            self.status_var.set("错误:请输入有效的数字")
            return
        
        # 获取单位和类别
        from_unit = self.from_unit_var.get()
        to_unit = self.to_unit_var.get()
        category = self.category_var.get()
        
        if not from_unit or not to_unit:
            messagebox.showerror("单位错误", "请选择源单位和目标单位")
            self.status_var.set("错误:请选择源单位和目标单位")
            return
        
        # 执行转换
        try:
            if category == "长度":
                result = self.convert_length(input_value, from_unit, to_unit)
            elif category == "质量":
                result = self.convert_mass(input_value, from_unit, to_unit)
            elif category == "温度":
                result = self.convert_temperature(input_value, from_unit, to_unit)
            elif category == "速度":
                result = self.convert_speed(input_value, from_unit, to_unit)
            elif category == "面积":
                result = self.convert_area(input_value, from_unit, to_unit)
            elif category == "体积":
                result = self.convert_volume(input_value, from_unit, to_unit)
            else:
                result = input_value
            
            # 显示结果
            self.display_result(input_value, from_unit, result, to_unit)
            
            # 添加到历史记录
            history_entry = f"{input_value} {from_unit} = {result:.6f} {to_unit} [{category}]"
            self.conversion_history.append(history_entry)
            self.history_listbox.insert(tk.END, history_entry)
            
            self.status_var.set("转换成功")
            
        except Exception as e:
            messagebox.showerror("转换错误", f"转换过程中发生错误: {str(e)}")
            self.status_var.set(f"错误:{str(e)}")
    
    def display_result(self, input_value, from_unit, result, to_unit):
        """在结果框中显示转换结果"""
        self.result_text.config(state=tk.NORMAL)
        self.result_text.delete(1.0, tk.END)
        
        # 创建格式化输出
        output = f"  {input_value} {from_unit}\n= {result:.6f} {to_unit}\n\n"
        
        # 添加科学解释
        if "米" in from_unit or "米" in to_unit:
            output += "1 米 ≈ 39.37 英寸"
        elif "千克" in from_unit or "千克" in to_unit:
            output += "1 千克 ≈ 2.20462 磅"
        elif "摄氏度" in from_unit or "摄氏度" in to_unit:
            output += "水的冰点: 0°C = 32°F\n水的沸点: 100°C = 212°F"
        elif "千米/小时" in from_unit or "千米/小时" in to_unit:
            output += "1 千米/小时 ≈ 0.621371 英里/小时"
        elif "平方米" in from_unit or "平方米" in to_unit:
            output += "1 平方米 ≈ 10.7639 平方英尺"
        elif "升" in from_unit or "升" in to_unit:
            output += "1 升 ≈ 0.264172 加仑"
        
        self.result_text.insert(tk.END, output)
        self.result_text.config(state=tk.DISABLED)
    
    def clear_history(self):
        """清除历史记录"""
        self.history_listbox.delete(0, tk.END)
        self.conversion_history = []
        self.status_var.set("历史记录已清除")
    
    # 转换函数
    def convert_length(self, value, from_unit, to_unit):
        """长度单位转换"""
        # 转换为米
        to_meter = {
            "米 (m)": 1.0,
            "千米 (km)": 1000.0,
            "厘米 (cm)": 0.01,
            "毫米 (mm)": 0.001,
            "英寸 (in)": 0.0254,
            "英尺 (ft)": 0.3048,
            "码 (yd)": 0.9144,
            "英里 (mile)": 1609.344
        }
        
        meters = value * to_meter[from_unit]
        
        # 从米转换为目标单位
        return meters / to_meter[to_unit]
    
    def convert_mass(self, value, from_unit, to_unit):
        """质量单位转换"""
        # 转换为千克
        to_kilogram = {
            "克 (g)": 0.001,
            "千克 (kg)": 1.0,
            "毫克 (mg)": 0.000001,
            "磅 (lb)": 0.453592,
            "盎司 (oz)": 0.0283495,
            "吨 (t)": 1000.0
        }
        
        kilograms = value * to_kilogram[from_unit]
        
        # 从千克转换为目标单位
        return kilograms / to_kilogram[to_unit]
    
    def convert_temperature(self, value, from_unit, to_unit):
        """温度单位转换"""
        # 先转换为摄氏度
        if from_unit == "摄氏度 (°C)":
            celsius = value
        elif from_unit == "华氏度 (°F)":
            celsius = (value - 32) * 5/9
        elif from_unit == "开尔文 (K)":
            celsius = value - 273.15
        
        # 从摄氏度转换为目标单位
        if to_unit == "摄氏度 (°C)":
            return celsius
        elif to_unit == "华氏度 (°F)":
            return (celsius * 9/5) + 32
        elif to_unit == "开尔文 (K)":
            return celsius + 273.15
    
    def convert_speed(self, value, from_unit, to_unit):
        """速度单位转换"""
        # 转换为米/秒
        to_mps = {
            "米/秒 (m/s)": 1.0,
            "千米/小时 (km/h)": 0.277778,
            "英里/小时 (mph)": 0.44704,
            "节 (kn)": 0.514444,
            "马赫 (Ma)": 340.3  # 在标准大气条件下
        }
        
        mps = value * to_mps[from_unit]
        
        # 从米/秒转换为目标单位
        return mps / to_mps[to_unit]
    
    def convert_area(self, value, from_unit, to_unit):
        """面积单位转换"""
        # 转换为平方米
        to_square_meter = {
            "平方米 (m²)": 1.0,
            "平方千米 (km²)": 1000000.0,
            "公顷 (ha)": 10000.0,
            "平方英里 (mi²)": 2589988.11,
            "英亩 (acre)": 4046.86,
            "平方英尺 (ft²)": 0.092903
        }
        
        square_meters = value * to_square_meter[from_unit]
        
        # 从平方米转换为目标单位
        return square_meters / to_square_meter[to_unit]
    
    def convert_volume(self, value, from_unit, to_unit):
        """体积单位转换"""
        # 转换为立方米
        to_cubic_meter = {
            "立方米 (m³)": 1.0,
            "升 (L)": 0.001,
            "毫升 (mL)": 0.000001,
            "加仑 (gal)": 0.00378541,
            "立方英尺 (ft³)": 0.0283168
        }
        
        cubic_meters = value * to_cubic_meter[from_unit]
        
        # 从立方米转换为目标单位
        return cubic_meters / to_cubic_meter[to_unit]

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

 

功能说明

这个单位转换工具具有以下特点:

1. 多种转换类别
– 长度:米、千米、厘米、毫米、英寸、英尺、码、英里
– 质量:克、千克、毫克、磅、盎司、吨
– 温度:摄氏度、华氏度、开尔文
– 速度:米/秒、千米/小时、英里/小时、节、马赫
– 面积:平方米、平方千米、公顷、平方英里、英亩、平方英尺
– 体积:立方米、升、毫升、加仑、立方英尺

2. 用户友好的界面
– 直观的类别选择下拉菜单
– 清晰的输入和输出区域
– 单位选择组合框
– 转换结果展示框
– 转换历史记录

3. 附加功能
– 实时转换历史记录
– 一键清除历史
– 状态栏显示操作状态
– 支持回车键触发转换
– 结果区域显示相关科学知识

4. 错误处理
– 输入验证(确保输入的是数字)
– 单位选择验证
– 详细的错误提示

使用说明

1. 选择转换类别(默认为长度)
2. 在输入框中输入要转换的数值
3. 选择源单位和目标单位
4. 点击”转换”按钮或按回车键
5. 查看转换结果和相关信息
6. 所有转换记录会自动保存到历史记录区域

运行要求

只需安装Python(3.x版本)即可运行此程序,不需要额外安装其他库。程序使用了Python标准库中的tkinter模块来创建图形界面。

这个工具对于学生、工程师、科学家或任何需要进行单位转换的用户都非常实用,界面简洁直观,功能全面。

© 版权声明
THE END
喜欢就支持一下吧
点赞8赞赏 分享