1. 完整python脚本 calculator.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import messagebox, font
import math
import re

class Calculator:
    def __init__(self, root):
        self.root = root
        self.root.title("多功能计算器 v1.0")
        self.root.geometry("400x550")
        self.root.resizable(False, False)
        
        # 设置图标(如果有的话)
        # self.root.iconbitmap('calculator.ico')
        
        # 变量
        self.expression = ""
        self.result_var = tk.StringVar()
        self.result_var.set("0")
        self.history = []
        
        # 设置样式
        self.setup_styles()
        
        # 创建界面
        self.create_widgets()
        
    def setup_styles(self):
        """设置颜色样式"""
        self.colors = {
            'bg': '#f0f0f0',
            'display_bg': '#ffffff',
            'number_btn': '#e6e6e6',
            'operator_btn': '#ff9800',
            'function_btn': '#4caf50',
            'clear_btn': '#f44336',
            'equal_btn': '#2196f3',
            'text': '#333333',
            'text_light': '#ffffff'
        }
        
    def create_widgets(self):
        """创建界面组件"""
        # 显示区域
        display_frame = tk.Frame(self.root, height=120, bg=self.colors['display_bg'])
        display_frame.pack(fill=tk.X, padx=10, pady=(10, 5))
        display_frame.pack_propagate(False)
        
        # 历史记录显示
        self.history_label = tk.Label(
            display_frame, 
            text="", 
            anchor='e', 
            bg=self.colors['display_bg'],
            fg='#888888',
            font=('Arial', 10)
        )
        self.history_label.pack(fill=tk.X, padx=10, pady=(5, 0))
        
        # 当前输入/结果显示
        self.display = tk.Label(
            display_frame,
            textvariable=self.result_var,
            anchor='e',
            bg=self.colors['display_bg'],
            fg=self.colors['text'],
            font=('Arial', 24, 'bold')
        )
        self.display.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 按钮区域
        buttons_frame = tk.Frame(self.root, bg=self.colors['bg'])
        buttons_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 10))
        
        # 按钮布局
        buttons = [
            ['C', '⌫', '√', '^'],
            ['7', '8', '9', '/'],
            ['4', '5', '6', '*'],
            ['1', '2', '3', '-'],
            ['0', '.', '=', '+'],
            ['(', ')', 'sin', 'cos'],
            ['log', 'ln', 'π', 'e']
        ]
        
        # 创建按钮网格
        for i, row in enumerate(buttons):
            frame = tk.Frame(buttons_frame, bg=self.colors['bg'])
            frame.pack(fill=tk.BOTH, expand=True, pady=2)
            
            for j, text in enumerate(row):
                btn = self.create_button(frame, text)
                btn.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=2)
        
        # 状态栏
        status_bar = tk.Label(
            self.root,
            text="© 2024 多功能计算器 | 支持表达式计算",
            bd=1,
            relief=tk.SUNKEN,
            anchor=tk.W,
            font=('Arial', 8),
            bg=self.colors['bg']
        )
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)
        
    def create_button(self, parent, text):
        """创建按钮并设置样式"""
        # 根据按钮类型设置颜色
        if text in ['C', '⌫']:
            bg_color = self.colors['clear_btn']
            fg_color = self.colors['text_light']
        elif text in ['=', '√', '^', 'sin', 'cos', 'log', 'ln', 'π', 'e']:
            bg_color = self.colors['function_btn']
            fg_color = self.colors['text_light']
        elif text in ['+', '-', '*', '/', '(', ')']:
            bg_color = self.colors['operator_btn']
            fg_color = self.colors['text_light']
        else:
            bg_color = self.colors['number_btn']
            fg_color = self.colors['text']
        
        btn = tk.Button(
            parent,
            text=text,
            bg=bg_color,
            fg=fg_color,
            font=('Arial', 12, 'bold'),
            bd=1,
            relief=tk.RAISED,
            cursor='hand2',
            command=lambda: self.button_click(text)
        )
        
        # 绑定鼠标悬停效果
        btn.bind('<Enter>', lambda e: self.on_enter(e, btn, bg_color))
        btn.bind('<Leave>', lambda e: self.on_leave(e, btn, bg_color))
        
        return btn
    
    def on_enter(self, event, button, original_color):
        """鼠标悬停效果"""
        button.config(bg=self.darken_color(original_color))
    
    def on_leave(self, event, button, original_color):
        """鼠标离开效果"""
        button.config(bg=original_color)
    
    def darken_color(self, color):
        """颜色加深(用于悬停效果)"""
        # 简化处理,实际应用可以计算更精确的颜色
        return '#cccccc' if color == '#e6e6e6' else '#b3b3b3'
    
    def button_click(self, value):
        """按钮点击处理"""
        if value == 'C':
            self.clear()
        elif value == '⌫':
            self.backspace()
        elif value == '=':
            self.calculate()
        elif value == '√':
            self.add_to_expression('sqrt(')
        elif value == '^':
            self.add_to_expression('**')
        elif value == 'π':
            self.add_to_expression(str(math.pi))
        elif value == 'e':
            self.add_to_expression(str(math.e))
        elif value == 'sin':
            self.add_to_expression('sin(')
        elif value == 'cos':
            self.add_to_expression('cos(')
        elif value == 'log':
            self.add_to_expression('log10(')
        elif value == 'ln':
            self.add_to_expression('log(')
        else:
            self.add_to_expression(value)
    
    def add_to_expression(self, value):
        """添加到表达式"""
        current = self.result_var.get()
        if current == '0' or current == '错误':
            self.result_var.set(value)
        else:
            self.result_var.set(current + value)
    
    def clear(self):
        """清除所有"""
        self.expression = ""
        self.result_var.set("0")
        self.history_label.config(text="")
    
    def backspace(self):
        """退格"""
        current = self.result_var.get()
        if len(current) > 1:
            self.result_var.set(current[:-1])
        else:
            self.result_var.set("0")
    
    def calculate(self):
        """计算表达式"""
        try:
            expression = self.result_var.get()
            
            # 替换数学函数
            expression = expression.replace('sin(', 'math.sin(')
            expression = expression.replace('cos(', 'math.cos(')
            expression = expression.replace('sqrt(', 'math.sqrt(')
            expression = expression.replace('log10(', 'math.log10(')
            expression = expression.replace('log(', 'math.log(')
            
            # 安全检查 - 只允许安全的数学运算
            if not self.is_safe_expression(expression):
                raise ValueError("表达式包含不允许的操作")
            
            # 计算结果
            result = eval(expression, {"__builtins__": {}}, {"math": math})
            
            # 格式化结果
            if isinstance(result, float):
                if result.is_integer():
                    result = int(result)
                else:
                    result = round(result, 10)
                    # 移除末尾的0
                    result = str(result).rstrip('0').rstrip('.') if '.' in str(result) else result
            
            # 添加到历史
            self.history.append(f"{expression} = {result}")
            if len(self.history) > 5:
                self.history.pop(0)
            
            # 显示历史
            history_text = " | ".join(self.history[-3:])
            self.history_label.config(text=history_text)
            
            # 显示结果
            self.result_var.set(str(result))
            
        except ZeroDivisionError:
            self.result_var.set("除数不能为0")
        except Exception as e:
            self.result_var.set("错误")
            messagebox.showerror("计算错误", f"表达式无效: {str(e)}")
    
    def is_safe_expression(self, expression):
        """检查表达式是否安全"""
        # 允许的字符和函数
        allowed_pattern = r'^[0-9\s\+\-\*\/\(\)\.\,\[\]math\.sqrtmath\.sinmath\.cosmath\.logmath\.log10\=\^\_]+$'
        
        # 检查是否有危险的关键字
        dangerous = ['__', 'import', 'exec', 'eval', 'compile', 'open', 'file']
        for item in dangerous:
            if item in expression:
                return False
        
        return True
    
    def on_keypress(self, event):
        """键盘事件处理"""
        key = event.char
        if key.isdigit() or key in '+-*/.()':
            self.add_to_expression(key)
        elif key == '\r':  # Enter键
            self.calculate()
        elif key == '\x08':  # Backspace
            self.backspace()
        elif key == '\x1b':  # Escape
            self.clear()

def main():
    """主函数"""
    root = tk.Tk()
    app = Calculator(root)
    
    # 绑定键盘事件
    root.bind('<Key>', app.on_keypress)
    
    # 运行主循环
    root.mainloop()

if __name__ == "__main__":
    main()

2. 打包步骤

# 1. 安装PyInstaller
pip install pyinstaller

# 2. 进入脚本所在目录
cd D:\脚本路径

# 3. 基础打包(单文件)
pyinstaller --onefile --windowed calculator.py

# 4. 完整打包(带图标和详细信息)
pyinstaller --onefile --windowed ^
           --name="多功能计算器" ^
           --icon=calculator.ico ^
           --add-data="calculator.ico;." ^
           --version-file=version.txt ^
           calculator.py

3. 打包后的程序界面

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐