Python应用——制作一个计算器

1 设计思路

制作一个计算器需要考虑以下问题:

1、定义功能:确定计算器需要实现哪些功能,比如基本的加减乘除,或者更复杂的科学计算功能。
2、设计用户界面:设计图形用户界面(GUI)来与用户交互。
3、实现基本逻辑:编写代码来处理用户输入,执行计算,并输出结果。
4、测试与调试:确保每个功能都按预期工作,并处理可能的异常情况。
5、优化与扩展:根据需要添加更多功能,优化用户体验。

2 编写程序

示例代码:

import tkinter as tk

class CalculatorApp():
    # 初始化
    def __init__(self):
        self.init_vars()
        self.init_ui()

    # 初始化参数
    def init_vars(self):
        self.lists = []               # 记录整段输入内容,用于最后计算结果
        self.is_press_sign = False    # 记录运算符是否按下
        self.is_press_point = False   # 记录小数点是否按下

    # 创建UI界面
    def init_ui(self):
        # 显示面板
        self.root = tk.Tk()
        self.root.minsize(280, 395)   # 界面尺寸
        self.root.title('计算器')         
        # 文本框
        self.history_info = tk.StringVar(value='')    # 显示历史计算过程
        self.current_info = tk.StringVar(value='0')   # 显示当前结果
        label = tk.Label(self.root, font=('微软雅黑', 16), bg='#EEE9E9', fg='gray', anchor='se', textvariable=self.history_info)
        label.place(width=280, height=60)
        label2 = tk.Label(self.root, font=('微软雅黑', 20), bg='#EEE9E9', fg='black', anchor='se', textvariable=self.current_info)
        label2.place(y=60, width=280, height=60)
        # 数字键按键
        self.create_number_buttons()
        # 运算符号按键
        self.create_operator_buttons()
        # tk事件循环
        self.root.mainloop()

    # 创建数字按键
    def create_number_buttons(self):
        buttons = [
            # (键值, x坐标, y坐标)
            ('7', 0, 175), ('8', 70, 175), ('9', 140, 175),
            ('4', 0, 230), ('5', 70, 230), ('6', 140, 230),
            ('1', 0, 285), ('2', 70, 285), ('3', 140, 285),
            ('0', 70, 340),
        ]
        for text, x, y in buttons:
            btn = tk.Button(self.root, text=text, font=('微软雅黑', 16), fg='black', bd=0.5, command=lambda t=text: self.press_num(t))
            btn.place(x=x, y=y, width=70, height=55)

    # 创建符号按键
    def create_operator_buttons(self):
        buttons = [
            # (键值, x坐标, y坐标, 颜色, 回调)
            ('C', 0, 120, 'orange', lambda: self.press_compute('C')),
            ('←', 105, 120, 'black', lambda: self.press_compute('←')),
            ('÷', 210, 120, 'black', lambda: self.press_compute('/')),
            ('x', 210, 175, 'black', lambda: self.press_compute('*')),
            ('-', 210, 230, 'black', lambda: self.press_compute('-')),
            ('+', 210, 285, 'black', lambda: self.press_compute('+')),
            ('=', 210, 340, 'orange', lambda: self.press_compute('=')),
            ('%', 0, 340, 'black', lambda: self.press_compute('%')),
            ('.', 140, 340, 'black', lambda: self.press_compute('.')),
        ]
        for text, x, y, fg, command in buttons:
            btn = tk.Button(self.root, text=text, font=('微软雅黑', 16), fg=fg, bd=0.5, command=command)
            if text == 'C' or text == '←':  # 'C'和'←'键布局特殊处理
                btn.place(x=x, y=y, width=105, height=55)
            else:
                btn.place(x=x, y=y, width=70, height=55)

    # 数字键回调函数
    def press_num(self, num):
        if self.is_press_sign:  # 如果前一个按键按下的是运算符,前面输入的数字清0
            self.current_info.set('0')
            self.is_press_sign = False
            self.is_press_point = False
        old_num = self.current_info.get() # 获取前面已输入的数字
        if old_num == '0':
            self.current_info.set(num)
        else:
            new_num = old_num + num
            self.current_info.set(new_num)

    # 符号按键回调
    def press_compute(self, sign):
        num = self.current_info.get()  # 获取当前输入值
        if sign == 'C':    # 清除数据
            if not num == '0':
                self.current_info.set('0')
            else:
                self.lists.clear()
                self.history_info.set('')
        elif sign == '←':  # 退格
            new_num = 0                   # 新值
            if num[-1] == '.': # 前面有小数点,退格2位
                new_num = num[0:-2]
                self.is_press_point = False
            else:              # 前面有无数点,退格1位
                new_num = num[0:-1]
            if not new_num:  # 新值为空,重设0
                new_num = '0'
            self.current_info.set(new_num)
        elif sign == '.':  # 小数点处理
            if self.is_press_point == False:
                self.current_info.set(num + '.')
                self.is_press_point = True
        elif sign == '=': 
                if self.is_press_sign == False:
                    # 添加当前输入值并计算最终结果
                    self.lists.append(num)
                else:
                    # 删除上一个输入的运算符
                    self.lists.pop()
                compute_str = ''.join(self.lists)
                end_num = eval(compute_str)  # 使用eval()函数来计算最终运算的结果
                end_num = round(end_num, 8)  # 保留8位小数,若去掉,某些小数计算就可能会出现一点点偏差(比如3.14+1)
                self.current_info.set(end_num)
                self.history_info.set(compute_str + '=')
                self.lists.clear()
                self.is_press_point = False
                self.is_press_sign = False
        else: # 运算符(+-*/%)
            if self.is_press_sign == False:
                self.is_press_sign = True 
                self.lists.append(num)
                self.lists.append(sign)
                # 显示已输入内容
                compute_str = ''.join(self.lists)
                self.history_info.set(compute_str)
                self.is_press_point = False
            else:  
                # 覆盖上一个输入的运算符
                self.lists.pop()
                self.lists.append(sign)
                # 显示已输入内容
                compute_str = ''.join(self.lists)
                self.history_info.set(compute_str)

if __name__ == "__main__":
    CalculatorApp()

上述代码使用了tkinter库来创建图形用户界面。这个程序能够处理基本的算术运算,包括加、减、乘、除、百分比计算,以及处理小数点、清除(C)和退格(←)功能。

3 运行测试

运行结果如下:
在这里插入图片描述
注:目前测试暂未发现bug,但需要注意的是,这个程序最终是使用了eval()函数来计算表达式,这个函数可能会存在某些bug,比如:使用eval()函数计算字符串’3.14+1’,得到的结果是4.140000000000001,这个可能跟浮点数内存的存储方式和精度有关,但是对一个简易的计算器来说大体上是不影响的。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐