Python-Tkinter 计算器实现

前言

此文章中使用了 python 中自带的 tkinter 库来实现一个计算器。与普通计算器不同的是,我们要实现的计算机支持诸如 1+1+1 这样含有多个符号和 (1+1)\times2 这样含有括号的式子。

先让大家浏览一下最终结果。

正文

首先我们需要引入 tkinter 库。使用通配符 * 可以便捷地使用其中的内容。

from tkinter import *

然后我们写一个窗口类,以 tkinter 的 Tk 为父类,并初始化相关参数。

class TK(Tk):
    def __init__(self):
        super().__init__(className='计算器');
        self.geometry('250x250')
        self.resizable(0,0)

然后我们需要使用 ScrolledText(滚动文本框)类以显示式子,需要先导入。

from tkinter.scrolledtext import ScrolledText as stext

然后对其进行初始化。 

f1=Frame(self) # 将文本框放入一个Frame里,防止与下面的按钮产生布局冲突
self.sc = stext(f1, height=3, state='disabled') # state初始化为不可用,防止用户自主输入
self.sc.pack()

接下来我们写按钮。先实现数字、小数点、括号和运算符号键,因为它们的工作只是往文本框内添加内容,相对简单、套路。

f2=Frame(self)
# 将按钮的父类设为一个Frame并使用grid网格化布局,防止与文本框的pack冲突
Button(f2, text='7', width=5, height=2, command=lambda: self.insert('7')).grid(row=0, column=0)
Button(f2, text='8', width=5, height=2, command=lambda: self.insert('8')).grid(row=0, column=1)
Button(f2, text='9', width=5, height=2, command=lambda: self.insert('9')).grid(row=0, column=2)
Button(f2, text='4', width=5, height=2, command=lambda: self.insert('4')).grid(row=1, column=0)
Button(f2, text='5', width=5, height=2, command=lambda: self.insert('5')).grid(row=1, column=1)
Button(f2, text='6', width=5, height=2, command=lambda: self.insert('6')).grid(row=1, column=2)
Button(f2, text='(', width=5, height=2, command=lambda: self.insert('(')).grid(row=1, column=3)
Button(f2, text=')', width=5, height=2, command=lambda: self.insert(')')).grid(row=1, column=4)
Button(f2, text='1', width=5, height=2, command=lambda: self.insert('1')).grid(row=2, column=0)
Button(f2, text='2', width=5, height=2, command=lambda: self.insert('2')).grid(row=2, column=1)
Button(f2, text='3', width=5, height=2, command=lambda: self.insert('3')).grid(row=2, column=2)
Button(f2, text='+', width=5, height=2, command=lambda: self.insert('+')).grid(row=2, column=3)
Button(f2, text='-', width=5, height=2, command=lambda: self.insert('-')).grid(row=2, column=4)
Button(f2, text='0', width=5, height=2, command=lambda: self.insert('0')).grid(row=3, column=0)
Button(f2, text='.', width=5, height=2, command=lambda: self.insert('.')).grid(row=3, column=1)
Button(f2, text='×', width=5, height=2, command=lambda: self.insert('×')).grid(row=3, column=3)
Button(f2, text='÷', width=5, height=2, command=lambda: self.insert('÷')).grid(row=3, column=4)

对应的 insert 函数如下。

def insert(self,char):
    self.sc.config(state='normal') # 先将文本框设为可用
    self.sc.insert(END,char) # 加入字符
    self.sc.config(state='disabled') # 再将其设为不可用

 剩下的就是一些功能按键了,先实现 CE(即清空)键。

Button(f2, text='CE', width=5, height=2, command=self.CE).grid(row=0, column=3)

对应的 CE 函数如下。

def CE(self):
    self.sc.config(state='normal')
    self.sc.delete('1.0',END) # 文本框的删除操作,不懂的可以去学学
    self.sc.config(state='disabled')

然后是 ->(即backspace)键。

Button(f2, text='->', width=5, height=2, command=self.backspace).grid(row=0, column=4)

对应的 backspace 函数如下。

def backspace(self):
    self.sc.config(state='normal')
    self.sc.delete('end - 2 chars','end - 1 char') # 删除末尾一个字符
    self.sc.config(state='disabled')

最后是 =(即结果)键。

Button(f2, text='=', width=5, height=2, command=self.get_res).grid(row=3, column=2)

= 键的 get_res 函数较为复杂。首先我们先将文本框内的内容取出来,再对其进行处理。因为计算机无法识别 \times 和 \div,我们需将其转换为 * 和 /

def get_res(self):
    self.sc.config(state='normal')
    s=self.sc.get('1.0',END) # 获取文本框中的内容
    s2=''
    for i in s:
        if i=='×':
            s2+='*'
        elif i=='÷':
            s2+='/'
        else:
            s2+=i

然后,我们对 s2 使用一个奇妙函数—— eval, 它可以处理表达式、算式。但如果式子错误,它就会报错。所以我们需要使用异常处理 try-except-finally 代码块。

try:
    res=eval(s2) # 使用eval函数
    self.CE() # 清空文本框
    for i in str(res):
        self.insert(i) # 将答案输入至文本框中
    except:
        showerror('错误','请检查算式是否正确。') # 如果错误,弹出错误提示框(需导入)
    finally:
        self.sc.config(state='disabled')

这样我们的计算器就写好了,在最后还要加上运行代码,将 TK 类实例化。

总程序

以下是整合程序。

from tkinter import *
from tkinter.scrolledtext import ScrolledText as stext
from tkinter.messagebox import showerror

class TK(Tk):
    def __init__(self):
        super().__init__(className='计算器');
        self.geometry('250x250')
        self.resizable(0,0)

        f1=Frame(self)
        self.sc = stext(f1, height=3, state='disabled')
        self.sc.pack()

        f2=Frame(self)
        Button(f2, text='7', width=5, height=2, command=lambda: self.insert('7')).grid(row=0, column=0)
        Button(f2, text='8', width=5, height=2, command=lambda: self.insert('8')).grid(row=0, column=1)
        Button(f2, text='9', width=5, height=2, command=lambda: self.insert('9')).grid(row=0, column=2)
        Button(f2, text='4', width=5, height=2, command=lambda: self.insert('4')).grid(row=1, column=0)
        Button(f2, text='5', width=5, height=2, command=lambda: self.insert('5')).grid(row=1, column=1)
        Button(f2, text='6', width=5, height=2, command=lambda: self.insert('6')).grid(row=1, column=2)
        Button(f2, text='(', width=5, height=2, command=lambda: self.insert('(')).grid(row=1, column=3)
        Button(f2, text=')', width=5, height=2, command=lambda: self.insert(')')).grid(row=1, column=4)
        Button(f2, text='1', width=5, height=2, command=lambda: self.insert('1')).grid(row=2, column=0)
        Button(f2, text='2', width=5, height=2, command=lambda: self.insert('2')).grid(row=2, column=1)
        Button(f2, text='3', width=5, height=2, command=lambda: self.insert('3')).grid(row=2, column=2)
        Button(f2, text='+', width=5, height=2, command=lambda: self.insert('+')).grid(row=2, column=3)
        Button(f2, text='-', width=5, height=2, command=lambda: self.insert('-')).grid(row=2, column=4)
        Button(f2, text='0', width=5, height=2, command=lambda: self.insert('0')).grid(row=3, column=0)
        Button(f2, text='.', width=5, height=2, command=lambda: self.insert('.')).grid(row=3, column=1)
        Button(f2, text='×', width=5, height=2, command=lambda: self.insert('×')).grid(row=3, column=3)
        Button(f2, text='÷', width=5, height=2, command=lambda: self.insert('÷')).grid(row=3, column=4)

        Button(f2, text='CE', width=5, height=2, command=self.CE).grid(row=0, column=3)
        Button(f2, text='->', width=5, height=2, command=self.backspace).grid(row=0, column=4)
        Button(f2, text='=', width=5, height=2, command=self.get_res).grid(row=3, column=2)

        f1.pack(); f2.pack()
    def CE(self):
        self.sc.config(state='normal')
        self.sc.delete('1.0',END)
        self.sc.config(state='disabled')

    def backspace(self):
        self.sc.config(state='normal')
        self.sc.delete('end - 2 chars','end - 1 char')
        self.sc.config(state='disabled')

    def insert(self,char):
        self.sc.config(state='normal')
        self.sc.insert(END,char)
        self.sc.config(state='disabled')

    def get_res(self):
        self.sc.config(state='normal')
        s=self.sc.get('1.0',END)
        s2=''
        for i in s:
            if i=='×':
                s2+='*'
            elif i=='÷':
                s2+='/'
            else:
                s2+=i

        try:
            res=eval(s2)
            self.CE()
            for i in str(res):
                self.insert(i)
        except:
            showerror('错误','请检查算式是否正确。')
        finally:
            self.sc.config(state='disabled')

if __name__=='__main__': # 运行
    TK().mainloop() # 将TK实例化

制作不易,点个赞吧qaq

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值