【python+tkinter】图形界面简易计算器的实现

前言

本文是学习tkinter后的一个练手项目,整个项目是基于python+tkinter的,主要是实现一个图形页面的简易计算器。

为此,我还画了一个简易的原型图哈哈哈,一起来看看长啥样吧!

原型

我设想的原型大概长这么个样子,接下来就是实现了...

完整的代码放在下面,我加了注释,比较方便大家看懂QAQ

代码实现

python 复制代码
import tkinter as tk
from tkinter import messagebox

class Calculator: 
    def __init__(self):
        # 窗口初始化
        # 创建主窗口
        self.window = tk.Tk()
        # self.window.title("简易计算器")
        self.window.configure(bg="#d7d7d7")  # 设置窗口背景颜色为浅灰色

        # 数据初始化
        self.current_input = ''  # 存储当前数据内容
        self.result_var = tk.StringVar()  # StringVar 用于实现显示内容的自动更新

        self.create_widgets()

    # 创建所有区域组件
    def create_widgets(self):
        self.create_header()  # 头部区域
        self.create_display()  # 显示区域
        self.create_buttons()  # 按钮区域
    # 实现头部标题区域
    def create_header(self):
        header_frame = tk.Frame(self.window, bg='#d7d7d7')
        header_frame.pack(fill=tk.X, padx=10, pady=5)  # 管理header_frame框架在window父容器中的位置

        title_label = tk.Label(header_frame, text="简易计算器", bg='#d7d7d7', font=('Arial', 16, 'bold'))
        title_label.pack(pady=5, anchor='w')

    # 实现显示区域
    def create_display(self):


        display_frame = tk.Frame(self.window, bg='lightgrey')
        display_frame.pack(fill=tk.X, padx=10, pady=5) 

        self.display = tk.Entry(display_frame, textvariable=self.result_var, state='readonly', font=('Arial', 18, 'bold'), justify='right',)
        self.display.pack(fill=tk.X, ipady=10)


    # 实现按钮区域
    def create_buttons(self):
        button_frame = tk.Frame(self.window, bg='lightgrey', padx=10, pady=10)
        button_frame.pack(fill=tk.X, expand=True) 
        
        # 先统一配置网格权重
        for i in range(5):
            button_frame.grid_rowconfigure(i, weight=1)
        # 配置4列按钮的权重
        for j in range(4):
            button_frame.grid_columnconfigure(j, weight=1)

        # 定义按钮布局
        buttons = [
            ['7', '8', '9', '/'],
            ['4', '5', '6', '*'],  
            ['1', '2', '3', '-'],
            ['.', '0', '⌫', '+'],
            ['C', '=']
        ]

        for i, row in enumerate(buttons):
            for j, text in enumerate(row):
                if i == 4:  # 第五行特殊处理
                    if text == 'C':
                        self.create_button(button_frame, text, i, j, colspan=2, color='#d7d7d7')  # Clear键为浅灰色
                    else:  # '='
                        self.create_button(button_frame, text, i, j+1, colspan=2, color='#208537')  # =键墨绿色
                    
                else:            
                    if text in ['+', '-', '*', '/']:
                        self.create_button(button_frame, text, i, j, colspan=1, color='#f59a23')  # 运算符键为橙色
                    elif text == '⌫':
                        self.create_button(button_frame, text, i, j, colspan=1, color='#d7d7d7')  # 清除键为浅灰色
                    else:
                        self.create_button(button_frame, text, i, j, colspan=1, color='#ffffff')  # 数字键为白色

        
    # 创建单个按钮
    def create_button(self, parent, text, row, column, colspan, color='#ffffff'):
        # 设置固定宽度,确保所有按钮宽度一致
        button_width = 2 if len(text) <= 2 else 4  # 根据文本长度调整宽度
        
        button = tk.Button(
            parent,
            text = text, 
            font = ('Courier New', 14, 'bold'),  # 使用等宽字体
            bg = color,
            fg = 'black',
            relief = 'raised',  # 按钮的凸起效果
            borderwidth = 2,
            command = lambda t=text: self.button_click(t),
            width = button_width,  # 设置固定宽度
            padx = 10  # 增加内边距平衡显示
        )

        # 按钮布局
        button.grid(
            row=row, 
            column=column,
            columnspan=colspan,
            sticky='nsew',  # 全局拉伸
            padx=2,
            pady=2
        )       

    # 按钮点击事件
    def button_click(self, value):
        if value.isdigit() or value == '.':  # 数字或小数点
            self.current_input += value
            self.result_var.set(self.current_input)  # 更新显示内容

        elif value in ['+', '-', '*', '/']:
            # 如果当前输入为空,或者当前输入按最后一个字符不是运算符,则添加运算符    
            if self.current_input and self.current_input[-1] not in ['+', '-', "*", '/']:
                self.current_input += value
                self.result_var.set(self.current_input)

        elif value == '⌫':
            if self.current_input:  # 如果当前输入有内容,则执行清除操作
                self.current_input = self.current_input[:-1]  # 清除最后一个字符
                self.result_var.set(self.current_input if self.current_input else '0')

        elif value == 'C':
            self.current_input = ''
            self.result_var.set('0')
            
        elif value == '=':  
            self.calculate_result()

    def calculate_result(self):
        try:
            if self.current_input:
                expression = self.current_input
                result = eval(expression)
                # 格式化结果
                if isinstance(result, float):
                    # 移除末尾多余的0和小数点
                    result_str = format(result, '.10g').rstrip('0').rstrip('.') if '.' in format(result, '.10g') else str(int(result))
                else:
                    result_str = str(result)

                self.result_var.set(result_str)
                self.current_input = result_str
        except ZeroDivisionError:
            messagebox.showerror("错误", "0不能作除数!")
            self.current_input = ''
            self.result_var.set('0')
        except Exception as e:
            messagebox.showerror("错误", "表达式无效!")
            self.current_input = ''
            self.result_var.set('0')
            
    def run(self):
        self.window.mainloop()
        

if __name__ == "__main__":
    c1 = Calculator()
    c1.run()

最终的执行结果...

虽然跟原型有点两模两样的吧,但是,你别管,我们的目的是将语法从理论状态下转到实际应用中,深入理解语法的含义(编不下去了...)

实际演示

差不多到这里就完成了,初学tkinter的小伙伴可以参考一下。

相关推荐
2301_812914872 小时前
py day34 装饰器
开发语言·python
卡提西亚3 小时前
C++笔记-24-文件读写操作
开发语言·c++·笔记
snakecy3 小时前
树莓派学习资料共享
大数据·开发语言·学习·系统架构
我的xiaodoujiao3 小时前
使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 24--数据驱动--参数化处理 Excel 文件 1
python·学习·测试工具·pytest
Nebula_g3 小时前
C语言应用实例:学生管理系统1(指针、结构体综合应用,动态内存分配)
c语言·开发语言·学习·算法·基础
开心-开心急了3 小时前
关于Flutter与Qt for python 的一些技术、开源、商用等问题
开发语言·python·qt·flutter
友友马3 小时前
『 QT 』按钮类控件属性解析
开发语言·数据库·qt
Evand J3 小时前
【MATLAB例程】基于噪声协方差自适应的互补滤波器方法vs标准互补滤波,用于融合加速度计和陀螺仪数据,估计角度
开发语言·matlab
熊小猿3 小时前
RabbitMQ死信交换机与延迟队列:原理、实现与最佳实践
开发语言·后端·ruby