注释都在文中写好了,十分详细,不多解释直接上代码
先让大家看看效果如何,具体操作还有各种用法,可以参考help里面的选项卡,file菜单中可以实现一些简单的操作,换算菜单中也内置了一些操作。
时间仓促,没能内置很多模块,不过可扩展性强,实现简单,大家可以自己动手来实现一些自己想要的功能。
大家可以去查看我博客里面的下载内容,有关于这个计算机程序的
- 源码
- 64位应用程序
- 32位应用程序
大家可以参考下载使用,注意:我Python的版本是3.7,要使用2.7版本的Python来编码的话,可能会有问题。
#计算器
#第一部分——导入库和库函数
import os
import re
import tkinter as tk
import random
import tkinter.messagebox
from math import *
#第二部分——对窗口、文本框的设置
#建新窗口—根窗口
root = tkinter.Tk()
#设置窗口的大小和位置
root.geometry("300x490+400+200")
#不允许改变高,不允许改变宽,0或False均可
root.resizable(0,False)
#设置窗口标题
root.title("计算器——刘元昊,郑倩霞,张美")
#在根窗口中建新一个以contentVar为控制变量的文本框,类型为可变文本框
contentVar = tkinter.StringVar(root,"")
# tkinter中,Entry表示单行文本框,Text表示多行文本框
# 用textvariable设置为可变文本,与StringVar可变文本框等配合使用
contentEntry = tkinter.Entry(root,textvariable = contentVar)
#将文本框状态设置为正常,即允许在文本框中进行键盘输入
contentEntry["state"] = "normal"
#设置文本框的位置,宽度和高度
contentEntry.place(x=10,y=10,width=280,height=20)
#第三部分——放置菜单和按钮
#(1)第一小部分放置按钮
#放置清除按钮和等号按钮,帮助与退出按钮
#传递给command属性的是函数对象,函数名后不能加括号,而这样定义的函数不能传递参数,
#而执行相应的操作,需要对不同参数进行处理,故需要重新定义一个函数,让这个函数调用另一个函数
#lambda是一种快速定义的最小函数(单行)
#注意:lambda 函数可以接收任意多个参数 (包括可选参数),并且返回单个表达式的值。
#lambda 函数不能包含命令,包含的表达式不能超过一个。
btnClear = tkinter.Button(root,text="Clear",command=lambda:buttonClick("Clear"))
btnClear.place(x=20,y=40,width=50,height=20)
btnDel = tkinter.Button(root,text="Del",command=lambda:buttonClick("Del"))
btnDel.place(x=90,y=40,width=50,height=20)
btnCompute = tkinter.Button(root,text="=",command=lambda:buttonClick("="))
btnCompute.place(x=230,y=40,width=50,height=20)
btnHelp = tkinter.Button(root,text="帮助",command=lambda:buttonClick("帮助"))
btnHelp.place(x=230,y=350,width=50,height=50)
btnQuit = tkinter.Button(root,text="退出",command=lambda:quit())
btnQuit.place(x=230,y=430,width=50,height=20)
#放置()[]按钮
signs = ["(",")","[","]"]
number = 0
for sign in signs:
number += 1
btnDigist = tkinter.Button(root,text=sign,command=lambda x=sign:buttonClick(x))
btnDigist.place(x=155+15*number,y=40,width=14,height=20)
#放置0123456789十个数字,小数点,计算平方根,调用三角反三角函数以及随机数和历史的按钮
digists = list("0123456789.") + ["Sqrt","sin(","cos(","tanx(","asin(","acos(",
"atan(","ceil(","floor(","abs(",",","随机数","历史"]
index = 0
for row in range(8):
for col in range(3):
d = digists[index]
index += 1
btnDigist = tkinter.Button(root,text=d,command=lambda x=d:buttonClick(x))
btnDigist.place(x=20 + col*70,y=80 + row*50,width = 50,height = 20)
#放置运算符按钮和π,e以及数学常数τ的近似值按钮
operators = ("+","-","*","/","**","//","pi","e","tau")
for index,operator in enumerate(operators):
btnOperator = tkinter.Button(root,text=operator,command=lambda x=operator:buttonClick(x))
btnOperator.place(x=230,y=80+index*30,width=50,height=20)
#(2)第二小部分放置菜单
m = tkinter.Menu(root)
root.config(menu=m)
#设置file选项
filemenu = tkinter.Menu(m)
m.add_cascade(label="File",menu=filemenu)
filemenu.add_command(label="New",command = lambda: callback("New"))
filemenu.add_separator()
filemenu.add_command(label="History",command=lambda:callback("History"))
filemenu.add_separator()
filemenu.add_command(label="Exit",command=lambda:quit())
filemenu.add_separator()
filemenu.add_command(label="top",command=lambda:root.wm_attributes("-topmost",1))
filemenu.add_separator()
#设置help选项
helpmenu = tkinter.Menu(m)
m.add_cascade(label="Help",menu=helpmenu)
list=['pi','e','tau','asin','//','**',"sqrt","随机数"]
list_explain=["pi:圆周率π的近似值","e:自然对数e的近似值",'tau:数学常数τ的近似值',
"""asin,acos,atan,分别代表反三角函数:
arcsin,arccos,arctan""","/:表示除号,//:表示整除","*:表示乘号,**:表示乘方",
"Sqrt:表示开方","随机数:random.randint(x,y),将生成一个在区间[x,y]之间的随机整数"]
index=0
help_dict={}
for i in list:
helpmenu.add_command(label=i,command=lambda x=i:callback(x))
help_dict[i]=list_explain[index]
index += 1
#设置换算选项#
changemenu=tkinter.Menu(m)
m.add_cascade(label="换算",menu=changemenu)
changemenu.add_command(label="BMI",command=lambda:callback("BMI"))
changemenu.add_separator()
changemenu.add_command(label="三维向量",command=lambda:callback("三维向量"))
changemenu.add_separator()
changemenu.add_command(label="信息1802抽签",command=lambda:callback("信息1802抽签"))
#第四部分——按钮处理代码和菜单处理代码
#(1)第一小部分按钮处理代码
def buttonClick(btn):
#获取录入框中的文本内容
content = contentVar.get()
#根据不同的按钮,做出相应的处理
#如果已有内容时以小数点开头的,前面加0
if content.startswith("."):
content = "0" + content + btn
#如果参数为Clear,清空文本框,如果参数为Del,去除最后一个字符
elif btn == "Clear":
content = ""
elif btn == "Del":
content = content[:-1]
#如果新输入字符串btn是小数点,且字符串content的个数大于1并以运算符结尾时,
#在小数点前加0,以数字结尾时,添加小数点,以ieu,结尾时报错,不对文本框内容做修改
elif btn == "." and len(content) >= 1:
if content[-1] in "()[]+-*/":
content = content + "0."
elif content[-1] in "0123456789":
content += btn
elif content[-1] in "ieu,":
tkinter.messagebox.showerror("错误:","π,eτ后不能有小数点")
return
#如果参数在"0123456789,()[]sin(cos(tan(pietauasin(acos(atan(ceil(floor(abs("之中,
#在文本框末尾直接加入此参数
elif btn in "0123456789,()[]sin(cos(tan(pietauasin(acos(atan(ceil(floor(abs(":
content += btn
#如果参数为帮助,则弹出帮助提示界面,内含相关按钮介绍及使用方法
elif btn == "帮助":
tkinter.messagebox.showinfo("帮助",""" pi:圆周率π的近似值
e:自然对数e的近似值
tau:数学常数τ的近似值
asin,acos,atan,分别代表反三角函数:
arcsin,arccos,arctan
/:表示除号
//:表示整除
*:表示乘号
**:表示乘方
Sqrt:表示开方
Clear:表示清空数据
del:表示退格,相当于电脑上的Backsace键
随机数:random.randint(x,y),将生成一个在区间[x,y]之间的随机整数
其他问题以及改进意见,请加QQ:273983336""")
elif btn == "历史":
pdw = os.getcwd()
infile = open(pdw + "\\history.txt","r")
text = infile.read()
infile.close()
tkinter.messagebox.showinfo("历史",text)
return
elif btn=="随机数":
content += "random.randint("
elif btn == "=":
try:
#对输入的表达式求值,并写入文件
#获取当前文件所在的路径
pdw = os.getcwd()
outfile = open(pdw + "\\history.txt","a")
outfile.write(content)
content = str(round(eval(content),10))
outfile.write("=" + content + "\n")
outfile.close()
except:
tkinter.messagebox.showerror("错误","表达式错误")
return
elif btn in operators:
if content.endswith(operators):
tkinter.messagebox.showerror("错误","不允许连续运算符")
return
content += btn
#如果参数为Sqrt,则
elif btn == "Sqrt":
try:
content = eval(content) ** 0.5
except:
tkinter.messagebox.showerror("错误","表达式错误")
contentVar.set(content)
#(2)第二小部分菜单处理代码
def callback(btn):
content = contentVar.get()
if btn == "New":
content = ""
elif btn == "History":
pdw = os.getcwd()
infile = open(pdw + "\\history.txt","r")
text = infile.read()
infile.close()
tkinter.messagebox.showinfo("历史",text)
return
elif btn in list:
tkinter.messagebox.showinfo("Help",help_dict[btn])
return
elif btn == "BMI":
window_BMI=tk.Toplevel(root)
window_BMI.geometry("350x200")
window_BMI.title("这是一个计算BMI的程序")
height=tk.StringVar()
tk.Label(window_BMI,text="请输入身高(米):").place(x=10,y=10)
tk.Entry(window_BMI,textvariable=height).place(x=150,y=10)
weight=tk.StringVar()
tk.Label(window_BMI,text="请输入体重(千克):").place(x=10,y=50)
tk.Entry(window_BMI,textvariable=weight).place(x=150,y=50)
btnBMI = tk.Button(window_BMI,text="计算",command=lambda:BMI())
btnBMI.place(x=10,y=90,height=30,width=50)
out_BMI=tk.StringVar()
tk.Label(window_BMI,text="BMI指数:").place(x=10,y=130)
tk.Entry(window_BMI,textvariable=out_BMI).place(x=150,y=130)
out_standard=tk.StringVar()
tk.Label(window_BMI,text="指标水平:").place(x=10,y=170)
tk.Entry(window_BMI,textvariable=out_standard).place(x=150,y=170)
def BMI():
new_height=float(height.get())
new_weight=float(weight.get())
BMI = round(new_weight / new_height ** 2 ,2)
out_BMI.set(BMI)
if BMI >= 18.5 and BMI <= 23.9:
out_standard.set("健康")
else:
out_standard.set("非正常")
elif btn == "三维向量":
window_vector=tk.Toplevel(root)
window_vector.geometry("350x400")
window_vector.title("三维向量的运算")
vector1=tk.StringVar()
tk.Label(window_vector,text="请输入向量v=(x,y,z)形如x,y,z,逗号为英文输入法下的逗号").place(x=10,y=10)
tk.Label(window_vector,text="V1=").place(x=20,y=40)
tk.Entry(window_vector,textvariable=vector1).place(x=100,y=40)
vector2=tk.StringVar()
tk.Label(window_vector,text="V2=").place(x=20,y=80)
tk.Entry(window_vector,textvariable=vector2).place(x=100,y=80)
btnvector=tk.Button(window_vector,text="计算",command=lambda:vector())
btnvector.place(x=10,y=120,height=30,width=50)
#定义一个三维向量的类(重载运算符)
#让类拦截常规的Python运算,重载是通过特殊名称的类方法来实现的
#运算符重载只是意味着在类方法中拦截内置的操作——
#当类的实例出现在内置操作中,Python自动调用你的方法,
#并且你的方法的返回值变成了相应操作的结果。
class Vector3:
def __init__(self,x,y,z):
self.x=x
self.y=y
self.z=z
#重载 +,-,*,**
def __add__(self,obj):
return Vector3(self.x + obj.x,self.y + obj.y,self.z + obj.z)
def __sub__(self,obj):
return Vector3(self.x - obj.x,self.y - obj.y,self.z - obj.z)
def __mul__(self,obj):
return Vector3(self.x * obj.x,self.y * obj.y,self.z * obj.z)
def __str__(self):
return str(self.x) + "," + str(self.y) + "," + str(self.z)
# 向量的外积,(x1,y1,z1) x (x2,y2,z2)=(y1z2 - y2z1,z1x2-z2x1,x1y2-x2y1)
def __pow__(self,obj):
return Vector3(self.y*obj.z - obj.y*self.z,
self.z*obj.x - obj.z*self.x,self.x*obj.y - obj.x*self.y)
def vector():
v1=vector1.get()
v2=vector2.get()
l=re.split(",",v1)+re.split(",",v2)
print(l)
x,y,z,m,n,l=int(l[0]),int(l[1]),int(l[2]),int(l[3]),int(l[4]),int(l[5])
V1=Vector3(x,y,z)
V2=Vector3(m,n,l)
out_add=tk.StringVar()
tk.Label(window_vector,text=" v1 + v2 = ").place(x=10,y=180)
tk.Entry(window_vector,textvariable=out_add).place(x=100,y=180)
out_add.set(V1+V2)
out_sub=tk.StringVar()
tk.Label(window_vector,text=" v1 - v2 = ").place(x=10,y=240)
tk.Entry(window_vector,textvariable=out_sub).place(x=100,y=240)
out_sub.set(V1-V2)
out_mul=tk.StringVar()
tk.Label(window_vector,text="内积:v1.v2=").place(x=10,y=300)
tk.Entry(window_vector,textvariable=out_mul).place(x=100,y=300)
out_mul.set(V1*V2)
out_pow=tk.StringVar()
tk.Label(window_vector,text="外积:v1Xv2=").place(x=10,y=350)
tk.Entry(window_vector,textvariable=out_pow).place(x=100,y=350)
out_pow.set(V1**V2)
elif btn == "信息1802抽签":
window_select = tk.Toplevel(root)
window_select.geometry("350x400")
window_select.title("信息1802抽签")
get_number = tk.StringVar()
tk.Label(window_select,text="请输入人数").place(x=10,y=10)
tk.Entry(window_select,textvariable=get_number).place(x=100,y=40)
lists=['钟锴\n', '李炯熠\n', '范小山\n', '栾福乔\n', '覃一耕\n', '王昭光\n', '刘元昊\n', '田浩江\n', '岳书豪\n', '赵展铭\n', '田昊伦\n', '贺言\n', '李子涵\n', '王欣\n', '李壮壮\n', '杨雨轩\n', '刘源\n', '王蕴达\n', '周子涵\n', '杨一磊\n', '涂志龙\n', '蔡舒妃\n', '张可怡\n', '胡芷莹\n', '韦洁媚\n', '贾玮\n', '许芷榕\n', '李瑞琪\n', '廖宁宁\n', '刘少聪\n', '杨思远\n', '成明珠\n']
btnnumber = tk.Button(window_select,text="抽取",command=lambda:what_number())
btnnumber.place(x=10,y=120,height=30,width=50)
def what_number():
content=''
number=int(get_number.get())
for i in range(1,number+1):
x=random.randint(1,len(lists))-1
content += lists[x] + " "
out_numbers=tk.StringVar()
tk.Entry(window_select,textvariable=out_numbers).place(x=10,y=250,width=280,height=20)
out_numbers.set(content)
contentVar.set(content)
#第五部分——进入主循环
#进入主(消息)循环,准备处理事件(必须组建),除非用户关闭窗口(或者按退出键),
#否则程序将一直处于主循环中
#注意:只有进入了主循环,根窗口才可见
root.mainloop()