当前位置: 代码网 > it编程>前端脚本>Python > 基于Python的tkinter库开发一个计算器的完整代码

基于Python的tkinter库开发一个计算器的完整代码

2025年07月07日 Python 我要评论
一、功能需求 我们希望实现的这个计算器应用程序,具有以下特点:1.功能齐全:基本运算:加、减、乘、除高级运算:平方根、百分比、幂运算三角函数:sin、cos、tan对数运算:自然对数 (ln)、常

一、功能需求        

我们希望实现的这个计算器应用程序,具有以下特点:

1.功能齐全:

  • 基本运算:加、减、乘、除
  • 高级运算:平方根、百分比、幂运算
  • 三角函数:sin、cos、tan
  • 对数运算:自然对数 (ln)、常用对数 (log)
  • 常数:π

2.用户界面友好:

  • 清晰的显示区域,分为历史记录和当前表达式
  • 颜色区分不同类型的按钮(数字、运算符、功能键)
  • 响应式字体大小,适应长表达式
  • 支持键盘输入,提高操作效率

3.使用说明:

  • 点击按钮或使用键盘输入表达式
  • 按 "=" 或回车键计算结果
  • "c" 键清除所有内容
  • "⌫" 键删除最后一个字符
  • 三角函数接受角度值

二、完整代码以及运行效果

1.完整代码

将以下代码,复制到开发工具中,通过cmd,这个应用程序可以直接运行,无需额外安装库。如需扩展功能,可以在代码中添加更多的按钮和对应的计算方法。

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

class calculator:
    def __init__(self, root):
        self.root = root
        self.root.title("高级计算器")
        self.root.geometry("400x600")
        self.root.resizable(false, false)
        self.root.configure(bg="#f0f0f0")
        
        # 设置字体
        self.display_font = font.font(family="simhei", size=24)
        self.button_font = font.font(family="simhei", size=14)
        
        # 计算变量
        self.current_expression = ""
        self.last_result = ""
        self.is_new_calculation = true
        
        # 创建界面
        self._create_display()
        self._create_buttons()
        
        # 绑定键盘事件
        self.root.bind("<key>", self._handle_key_event)
    
    def _create_display(self):
        # 历史记录显示
        self.history_frame = tk.frame(self.root, bg="#f0f0f0", height=50)
        self.history_frame.pack(fill=tk.x, padx=10, pady=(10, 0))
        self.history_frame.pack_propagate(0)
        
        self.history_label = tk.label(
            self.history_frame, 
            text="", 
            bg="#f0f0f0", 
            fg="#888", 
            font=self.display_font,
            anchor=tk.e
        )
        self.history_label.pack(fill=tk.both, padx=5)
        
        # 当前表达式显示
        self.display_frame = tk.frame(self.root, bg="#f0f0f0", height=80)
        self.display_frame.pack(fill=tk.x, padx=10, pady=5)
        self.display_frame.pack_propagate(0)
        
        self.display = tk.entry(
            self.display_frame, 
            font=self.display_font, 
            bg="white", 
            fg="black", 
            justify=tk.right,
            bd=5,
            relief=tk.sunken
        )
        self.display.pack(fill=tk.both, padx=5, pady=5)
        self.display.insert(0, "0")
        self.display.configure(state="readonly")
    
    def _create_buttons(self):
        button_frame = tk.frame(self.root, bg="#f0f0f0")
        button_frame.pack(fill=tk.both, expand=true, padx=10, pady=10)
        
        # 定义按钮布局
        buttons = [
            ("7", 1, 0), ("8", 1, 1), ("9", 1, 2), ("/", 1, 3), ("c", 1, 4),
            ("4", 2, 0), ("5", 2, 1), ("6", 2, 2), ("*", 2, 3), ("⌫", 2, 4),
            ("1", 3, 0), ("2", 3, 1), ("3", 3, 2), ("-", 3, 3), ("(", 3, 4),
            ("0", 4, 0), (".", 4, 1), ("=", 4, 2), ("+", 4, 3), (")", 4, 4),
            ("%", 5, 0), ("√", 5, 1), ("^", 5, 2), ("π", 5, 3), ("sin", 5, 4),
            ("cos", 6, 0), ("tan", 6, 1), ("ln", 6, 2), ("log", 6, 3), ("1/x", 6, 4)
        ]
        
        # 创建按钮
        for button_data in buttons:
            text, row, col = button_data
            
            # 设置按钮样式
            if text == "=":
                bg_color = "#4caf50"
                fg_color = "white"
            elif text == "c" or text == "⌫":
                bg_color = "#f44336"
                fg_color = "white"
            elif col == 3 or col == 4:
                bg_color = "#2196f3"
                fg_color = "white"
            else:
                bg_color = "#e0e0e0"
                fg_color = "black"
            
            # 创建按钮
            button = tk.button(
                button_frame,
                text=text,
                font=self.button_font,
                bg=bg_color,
                fg=fg_color,
                relief=tk.raised,
                bd=3,
                padx=10,
                pady=10,
                command=lambda txt=text: self._button_click(txt)
            )
            
            # 设置按钮网格
            button.grid(row=row, column=col, padx=5, pady=5, sticky="nsew")
        
        # 设置网格权重,使按钮均匀分布
        for i in range(7):
            button_frame.grid_rowconfigure(i, weight=1)
        for i in range(5):
            button_frame.grid_columnconfigure(i, weight=1)
    
    def _button_click(self, text):
        # 处理按钮点击事件
        if text == "c":
            self._clear_all()
        elif text == "⌫":
            self._backspace()
        elif text == "=":
            self._calculate()
        elif text == "π":
            self._append_value(str(math.pi))
        elif text == "√":
            self._calculate_sqrt()
        elif text == "^":
            self._append_value("**")
        elif text == "sin":
            self._calculate_trig("sin")
        elif text == "cos":
            self._calculate_trig("cos")
        elif text == "tan":
            self._calculate_trig("tan")
        elif text == "ln":
            self._calculate_ln()
        elif text == "log":
            self._calculate_log()
        elif text == "1/x":
            self._calculate_reciprocal()
        elif text == "%":
            self._calculate_percentage()
        else:
            self._append_value(text)
    
    def _handle_key_event(self, event):
        # 处理键盘事件
        key = event.char
        
        if key.isdigit() or key in "+-*/().":
            self._append_value(key)
        elif key == "\r" or key == "=":
            self._calculate()
        elif key == "\x08":  # backspace
            self._backspace()
        elif key.lower() == "c":
            self._clear_all()
    
    def _append_value(self, value):
        # 追加值到当前表达式
        if self.is_new_calculation:
            self.current_expression = ""
            self.is_new_calculation = false
        
        if self.current_expression == "0" and value.isdigit():
            self.current_expression = value
        else:
            self.current_expression += value
        
        self._update_display()
    
    def _clear_all(self):
        # 清除所有内容
        self.current_expression = ""
        self.history_label.config(text="")
        self.is_new_calculation = true
        self._update_display()
    
    def _backspace(self):
        # 删除最后一个字符
        if not self.is_new_calculation and self.current_expression:
            self.current_expression = self.current_expression[:-1]
            self._update_display()
    
    def _update_display(self):
        # 更新显示内容
        self.display.configure(state="normal")
        self.display.delete(0, tk.end)
        
        # 格式化显示内容
        display_text = self.current_expression
        
        # 检查表达式长度,如果太长则缩小字体
        if len(display_text) > 15:
            self.display_font.configure(size=18)
        else:
            self.display_font.configure(size=24)
        
        self.display.insert(0, display_text)
        self.display.configure(state="readonly")
    
    def _calculate(self):
        # 计算表达式结果
        if not self.current_expression or self.is_new_calculation:
            return
        
        try:
            # 替换π和e
            expression = self.current_expression
            expression = re.sub(r'π', str(math.pi), expression)
            expression = re.sub(r'e', str(math.e), expression)
            
            # 计算结果
            result = eval(expression)
            
            # 格式化结果
            if isinstance(result, float):
                # 处理浮点数精度
                if result.is_integer():
                    result = int(result)
                else:
                    result = round(result, 10)
            
            # 更新历史记录
            self.history_label.config(text=f"{self.current_expression} = {result}")
            
            # 更新当前表达式
            self.current_expression = str(result)
            self.last_result = str(result)
            self.is_new_calculation = true
            
            self._update_display()
            
        except exception as e:
            self.display.configure(state="normal")
            self.display.delete(0, tk.end)
            self.display.insert(0, "错误")
            self.display.configure(state="readonly")
            self.current_expression = ""
            self.is_new_calculation = true
    
    def _calculate_sqrt(self):
        # 计算平方根
        if not self.current_expression or self.is_new_calculation:
            return
        
        try:
            value = float(self.current_expression)
            if value < 0:
                raise valueerror("平方根不能为负数")
            
            result = math.sqrt(value)
            
            # 更新历史记录
            self.history_label.config(text=f"√{self.current_expression} = {result}")
            
            # 更新当前表达式
            self.current_expression = str(result)
            self.last_result = str(result)
            self.is_new_calculation = true
            
            self._update_display()
            
        except exception as e:
            self.display.configure(state="normal")
            self.display.delete(0, tk.end)
            self.display.insert(0, "错误")
            self.display.configure(state="readonly")
            self.current_expression = ""
            self.is_new_calculation = true
    
    def _calculate_trig(self, func):
        # 计算三角函数
        if not self.current_expression or self.is_new_calculation:
            return
        
        try:
            value = float(self.current_expression)
            # 假设输入是角度,转换为弧度
            radians = math.radians(value)
            
            if func == "sin":
                result = math.sin(radians)
            elif func == "cos":
                result = math.cos(radians)
            elif func == "tan":
                result = math.tan(radians)
            else:
                result = "错误"
            
            # 更新历史记录
            self.history_label.config(text=f"{func}({self.current_expression}°) = {result}")
            
            # 更新当前表达式
            self.current_expression = str(result)
            self.last_result = str(result)
            self.is_new_calculation = true
            
            self._update_display()
            
        except exception as e:
            self.display.configure(state="normal")
            self.display.delete(0, tk.end)
            self.display.insert(0, "错误")
            self.display.configure(state="readonly")
            self.current_expression = ""
            self.is_new_calculation = true
    
    def _calculate_ln(self):
        # 计算自然对数
        if not self.current_expression or self.is_new_calculation:
            return
        
        try:
            value = float(self.current_expression)
            if value <= 0:
                raise valueerror("对数的真数必须大于0")
            
            result = math.log(value)
            
            # 更新历史记录
            self.history_label.config(text=f"ln({self.current_expression}) = {result}")
            
            # 更新当前表达式
            self.current_expression = str(result)
            self.last_result = str(result)
            self.is_new_calculation = true
            
            self._update_display()
            
        except exception as e:
            self.display.configure(state="normal")
            self.display.delete(0, tk.end)
            self.display.insert(0, "错误")
            self.display.configure(state="readonly")
            self.current_expression = ""
            self.is_new_calculation = true
    
    def _calculate_log(self):
        # 计算常用对数
        if not self.current_expression or self.is_new_calculation:
            return
        
        try:
            value = float(self.current_expression)
            if value <= 0:
                raise valueerror("对数的真数必须大于0")
            
            result = math.log10(value)
            
            # 更新历史记录
            self.history_label.config(text=f"log({self.current_expression}) = {result}")
            
            # 更新当前表达式
            self.current_expression = str(result)
            self.last_result = str(result)
            self.is_new_calculation = true
            
            self._update_display()
            
        except exception as e:
            self.display.configure(state="normal")
            self.display.delete(0, tk.end)
            self.display.insert(0, "错误")
            self.display.configure(state="readonly")
            self.current_expression = ""
            self.is_new_calculation = true
    
    def _calculate_reciprocal(self):
        # 计算倒数
        if not self.current_expression or self.is_new_calculation:
            return
        
        try:
            value = float(self.current_expression)
            if value == 0:
                raise zerodivisionerror("不能除以零")
            
            result = 1 / value
            
            # 更新历史记录
            self.history_label.config(text=f"1/{self.current_expression} = {result}")
            
            # 更新当前表达式
            self.current_expression = str(result)
            self.last_result = str(result)
            self.is_new_calculation = true
            
            self._update_display()
            
        except exception as e:
            self.display.configure(state="normal")
            self.display.delete(0, tk.end)
            self.display.insert(0, "错误")
            self.display.configure(state="readonly")
            self.current_expression = ""
            self.is_new_calculation = true
    
    def _calculate_percentage(self):
        # 计算百分比
        if not self.current_expression or self.is_new_calculation:
            return
        
        try:
            value = float(self.current_expression)
            result = value / 100
            
            # 更新历史记录
            self.history_label.config(text=f"{self.current_expression}% = {result}")
            
            # 更新当前表达式
            self.current_expression = str(result)
            self.last_result = str(result)
            self.is_new_calculation = true
            
            self._update_display()
            
        except exception as e:
            self.display.configure(state="normal")
            self.display.delete(0, tk.end)
            self.display.insert(0, "错误")
            self.display.configure(state="readonly")
            self.current_expression = ""
            self.is_new_calculation = true

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

2.运行效果

打开cmd,写上“py+空格”,将文件拖入,回车运行即可。

三、代码详细解析

这个计算器应用程序基于 python 的 tkinter 库开发,具有友好的用户界面和丰富的计算功能。下面我将从整体架构到具体功能逐步解析代码:

1.整体架构

代码采用面向对象的方式组织,核心是calculator类,它负责:

  • 创建和管理图形界面
  • 处理用户输入(按钮点击和键盘事件)
  • 执行计算逻辑
  • 更新显示内容

2.初始化与界面设置

calculator类中有一个初始化方法__init__(),实例化了一个gui对象,并设置标题、窗体大小、是否可放大缩小,以及背景颜色配置。

class calculator:
    def __init__(self, root):
        self.root = root
        self.root.title("高级计算器")
        self.root.geometry("400x600")
        self.root.resizable(false, false)
        self.root.configure(bg="#f0f0f0")
        
        # 设置字体
        self.display_font = font.font(family="simhei", size=24)
        self.button_font = font.font(family="simhei", size=14)
        
        # 计算变量
        self.current_expression = ""
        self.last_result = ""
        self.is_new_calculation = true
        
        # 创建界面
        self._create_display()
        self._create_buttons()
        
        # 绑定键盘事件
        self.root.bind("<key>", self._handle_key_event)

代码说明:

  • 窗口大小固定为 400x600 像素,不可调整
  • 使用两种字体分别显示表达式和按钮文本
  • 三个关键变量:
    • current_expression:当前输入的表达式
    • last_result:上一次计算的结果
    • is_new_calculation:标记是否开始新的计算

3.显示区域设计

包括当前输入的内容和上一次的计算记录,上一次的计算记录放在输入框上面。

def _create_display(self):
    # 历史记录显示
    self.history_frame = tk.frame(self.root, bg="#f0f0f0", height=50)
    self.history_frame.pack(fill=tk.x, padx=10, pady=(10, 0))
    self.history_frame.pack_propagate(0)
    
    self.history_label = tk.label(
        self.history_frame, 
        text="", 
        bg="#f0f0f0", 
        fg="#888", 
        font=self.display_font,
        anchor=tk.e
    )
    self.history_label.pack(fill=tk.both, padx=5)
    
    # 当前表达式显示
    self.display_frame = tk.frame(self.root, bg="#f0f0f0", height=80)
    self.display_frame.pack(fill=tk.x, padx=10, pady=5)
    self.display_frame.pack_propagate(0)
    
    self.display = tk.entry(
        self.display_frame, 
        font=self.display_font, 
        bg="white", 
        fg="black", 
        justify=tk.right,
        bd=5,
        relief=tk.sunken
    )
    self.display.pack(fill=tk.both, padx=5, pady=5)
    self.display.insert(0, "0")
    self.display.configure(state="readonly")

代码说明:

  • 分为两个显示区域:
    • 历史记录:显示上一次的计算表达式和结果
    • 当前表达式:显示正在输入的内容
  • 使用pack_propagate(0)固定框架大小
  • 显示区域使用凹陷边框 (relief=tk.sunken) 增强视觉效果

4.按钮布局与设计

所有的按钮用列表保存。

def _create_buttons(self):
    button_frame = tk.frame(self.root, bg="#f0f0f0")
    button_frame.pack(fill=tk.both, expand=true, padx=10, pady=10)
    
    # 定义按钮布局
    buttons = [
        ("7", 1, 0), ("8", 1, 1), ("9", 1, 2), ("/", 1, 3), ("c", 1, 4),
        ("4", 2, 0), ("5", 2, 1), ("6", 2, 2), ("*", 2, 3), ("⌫", 2, 4),
        ("1", 3, 0), ("2", 3, 1), ("3", 3, 2), ("-", 3, 3), ("(", 3, 4),
        ("0", 4, 0), (".", 4, 1), ("=", 4, 2), ("+", 4, 3), (")", 4, 4),
        ("%", 5, 0), ("√", 5, 1), ("^", 5, 2), ("π", 5, 3), ("sin", 5, 4),
        ("cos", 6, 0), ("tan", 6, 1), ("ln", 6, 2), ("log", 6, 3), ("1/x", 6, 4)
    ]
    
    # 创建按钮
    for button_data in buttons:
        text, row, col = button_data
        
        # 设置按钮样式
        if text == "=":
            bg_color = "#4caf50"  # 绿色
            fg_color = "white"
        elif text == "c" or text == "⌫":
            bg_color = "#f44336"  # 红色
            fg_color = "white"
        elif col == 3 or col == 4:
            bg_color = "#2196f3"  # 蓝色
            fg_color = "white"
        else:
            bg_color = "#e0e0e0"  # 灰色
            fg_color = "black"
            
        # 创建按钮并绑定事件
        ...

代码说明:

  • 使用 6x5 网格布局所有按钮
  • 不同功能的按钮使用不同颜色区分:
    • 等号:绿色
    • 清除和退格:红色
    • 运算符和功能键:蓝色
    • 数字键:灰色
  • 使用grid方法排列按钮,并设置sticky="nsew"使其填充整个单元格

5.核心计算功能

def _calculate(self):
    # 计算表达式结果
    if not self.current_expression or self.is_new_calculation:
        return
    
    try:
        # 替换π和e
        expression = self.current_expression
        expression = re.sub(r'π', str(math.pi), expression)
        expression = re.sub(r'e', str(math.e), expression)
        
        # 计算结果
        result = eval(expression)
        
        # 格式化结果
        if isinstance(result, float):
            if result.is_integer():
                result = int(result)
            else:
                result = round(result, 10)
        
        # 更新历史记录和显示
        ...
        
    except exception as e:
        self.display.configure(state="normal")
        self.display.delete(0, tk.end)
        self.display.insert(0, "错误")
        self.display.configure(state="readonly")
        self.current_expression = ""
        self.is_new_calculation = true

代码说明:

  • 使用 python 内置的eval()函数计算表达式
  • 支持 π 和 e 等数学常数
  • 处理浮点数精度问题,避免显示过长的小数
  • 包含异常处理,当表达式错误时显示 "错误"

6.高级数学功能

计算器能实现多种基本的数学运算。

def _calculate_sqrt(self):
    # 计算平方根
    if not self.current_expression or self.is_new_calculation:
        return
    
    try:
        value = float(self.current_expression)
        if value < 0:
            raise valueerror("平方根不能为负数")
        
        result = math.sqrt(value)
        
        # 更新历史记录和显示
        ...
        
    except exception as e:
        self.display.configure(state="normal")
        self.display.delete(0, tk.end)
        self.display.insert(0, "错误")
        self.display.configure(state="readonly")
        self.current_expression = ""
        self.is_new_calculation = true

def _calculate_trig(self, func):
    # 计算三角函数
    if not self.current_expression or self.is_new_calculation:
        return
    
    try:
        value = float(self.current_expression)
        # 假设输入是角度,转换为弧度
        radians = math.radians(value)
        
        if func == "sin":
            result = math.sin(radians)
        elif func == "cos":
            result = math.cos(radians)
        elif func == "tan":
            result = math.tan(radians)
        else:
            result = "错误"
        
        # 更新历史记录和显示
        ...
        
    except exception as e:
        self.display.configure(state="normal")
        self.display.delete(0, tk.end)
        self.display.insert(0, "错误")
        self.display.configure(state="readonly")
        self.current_expression = ""
        self.is_new_calculation = true

代码说明:

  • 平方根计算:检查输入是否为非负数
  • 三角函数:将角度转换为弧度进行计算
  • 所有高级功能都有错误处理机制

7.用户输入处理

def _button_click(self, text):
    # 处理按钮点击事件
    if text == "c":
        self._clear_all()
    elif text == "⌫":
        self._backspace()
    elif text == "=":
        self._calculate()
    elif text == "π":
        self._append_value(str(math.pi))
    elif text == "√":
        self._calculate_sqrt()
    elif text == "^":
        self._append_value("**")
    elif text in ["sin", "cos", "tan"]:
        self._calculate_trig(text)
    elif text == "ln":
        self._calculate_ln()
    elif text == "log":
        self._calculate_log()
    elif text == "1/x":
        self._calculate_reciprocal()
    elif text == "%":
        self._calculate_percentage()
    else:
        self._append_value(text)

def _handle_key_event(self, event):
    # 处理键盘事件
    key = event.char
    
    if key.isdigit() or key in "+-*/().":
        self._append_value(key)
    elif key == "\r" or key == "=":
        self._calculate()
    elif key == "\x08":  # backspace
        self._backspace()
    elif key.lower() == "c":
        self._clear_all()

代码说明:

  • 按钮点击和键盘输入都有相应的处理函数
  • 支持数字、运算符和特殊字符输入
  • 回车键和等号都可以触发计算

8.动态字体调整

输入框长度是有限的,有时希望尽量能看清所有输入的字符,所以做了动态字体调整。

def _update_display(self):
    # 更新显示内容
    self.display.configure(state="normal")
    self.display.delete(0, tk.end)
    
    # 格式化显示内容
    display_text = self.current_expression
    
    # 检查表达式长度,如果太长则缩小字体
    if len(display_text) > 15:
        self.display_font.configure(size=18)
    else:
        self.display_font.configure(size=24)
    
    self.display.insert(0, display_text)
    self.display.configure(state="readonly")

代码说明:

  • 当表达式长度超过 15 个字符时,自动缩小字体大小
  • 保证长表达式也能完整显示在屏幕上

9.程序入口

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

代码说明:

  • 创建主窗口并启动应用程序
  • 通过mainloop()方法进入事件循环,等待用户交互

10.功能扩展建议

  • 添加记忆功能:增加 m+、m-、mr、mc 按钮用于存储和调用数值
  • 支持科学计数法:对于极大或极小的计算结果,使用科学计数法显示
  • 添加进制转换:支持二进制、八进制、十进制、十六进制之间的转换
  • 增加括号匹配提示:在输入括号时,用不同颜色提示匹配的括号
  • 历史记录扩展:保存多条历史计算记录,并支持查看和重复使用

这个计算器已经具备了基本和高级的计算功能,界面友好且易于使用。通过进一步扩展,可以使其成为更加强大的科学计算器。

以上就是基于python的tkinter库开发一个计算器的完整代码的详细内容,更多关于python tkinter计算器的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com