学号 20212217 姓名 刘恒谦 《Python程序设计》实验二报告
课程:《Python程序设计》
班级: 2122
姓名: 刘恒谦
学号:20212217
实验教师:王志强
实验日期:2022年4月4日
必修/选修: 公选课
1.实验内容
用pysimpleGUI库编写可视化的计算器
之所以选用 Default1这个风格,是因为它最接近微软计算器。
2. 实验过程及结果
(1)搭建PySimpleGUI的框架
(2)编写按钮,文本框2大前端控件
(3)增加数据运算,逻辑处理的后端设计
(4)简化代码,简洁美观
下图是PySimpleGUI的基础框架。
点击查看代码
import PySimpleGUI as sg
sg.theme("Default1")
layout=[
]
window=sg.Window("Besti~Calculator",layout,font="微软雅黑")
while True:
event,value=window.read()
if event==sg.WIN_CLOSED:
break
window.close()
3. 实验过程中遇到的问题和解决过程
- 问题1:字体大小难以修改,界面不美观。
- 问题1解决方案:
- 字体大小: 参考别人代码的过程中,我了解到PySimpleGUI文字大小和字体有关,默认的"Arial"字体仅仅只有6号大,而"微软雅黑"字体有3号大。为了尽可能接近windows11自带计算器的界面风格,我采用了"微软雅黑"字体,不过比例仍然稍有不同。另外,修改Window控件的字体会对其中所有的元素生效,也就是实现计算器文字大小字体的统一。
window=sg.Window("Besti~Calculator",layout,font="微软雅黑")
-
问题2:控件大小难以确定。
-
问题2解决方案:PySimpleGUI的控件被其称为"元素"(element),这些元素的大小取决于其上的文字。文字越多,控件越宽。而计算机中的 "1/x" 和 "/" 比,字体数量不统一,元素宽度也不一样。参照知乎的建议,我修改了auto_size_button参数,它默认是True,意味根据字体自动改变元素大小。现在改为False。
sg.Button("1/x",auto_size_button=False)
-
问题3:后端数学计算复杂
-
问题3解决方案:一般我们接受到x,就要去"乘",接受到 "=" ,就要去计算。这样很麻烦。要对各种运算符号写if elif 的代码。有没有更简单的办法呢?
当然是有的,eval() 函数可以对字符串中的Python数学表达式解析计算,返回一个数,可谓相当方便。我们只需将用户输入转化为字符串,再在判断相等时运用eval()函数就可以了。
其他(感悟、思考等)
使用微软计算器的时候我还发现它自带一个历史记录的功能。
其实只需用列表把每次的运算记录下来就可以了。并不复杂,于是我也做了一个。
这个"↺"标志其实也是跟windows11计算器学的。
完整代码见Gitee仓库
https://gitee.com/besti-cs/modest-warehouse/blob/master/Besti~calculator.py
另外运行这行代码前要确保你已经安装了PySImpleGUI噢
在终端中输入
python -m pip install --upgrade pip
回车
再输入
pip install pysimpleGUI -i https://pypi.mirrors.ustc.edu.cn/simple
回车
就可以运行下面这段代码了,(代码已折叠)
点击查看代码
import PySimpleGUI as sg
# import math
sg.theme("Default1")
layout=[
[sg.Text("标准"+" "*35), sg.Button("↺",size=(3,1),pad=(1,1),tooltip="历史记录",)],
[sg.Text(key="expression", size=(24,2))],
[sg.Text(key="result", size=(24,2))],
[sg.Button(word,size=(6,1),pad=(1,1)) for word in ["%", "CE", "C", "Del"]],
[sg.Button(word,size=(6,1),pad=(1,1)) for word in ["1/x", "x^2", "√", "÷"]],
[sg.Button(word,size=(6,1),pad=(1,1)) for word in ["7","8","9","x"]],
[sg.Button(word,size=(6,1),pad=(1,1)) for word in ["4","5","6","-"]],
[sg.Button(word,size=(6,1),pad=(1,1)) for word in ["1","2","3","+"]],
[sg.Button(word,size=(6,1),pad=(1,1)) for word in ["+/-","0",".","="]],
]
window=sg.Window("Besti~Calculator",layout,font="微软雅黑")
expression=""
result=""
history=[]
while True:
event,value=window.read()
if event==sg.WIN_CLOSED:
break
# "↺" 用于查看历史记录
elif event=="↺":
sg.Popup("历史记录\n"+"\n".join(history))
# "CE"用来删除历史记录
elif event=="CE":
history=[]
else:
if event=="=":
# 入口检查
try :
result= str(eval(expression))
except SyntaxError:
result= "表达式错误"
# 计算表达式并保存历史记录
window.Element("result").update(result)
history.append(f'{expression.replace("**", "x").replace("/", "÷")} ={result}')
elif event =="Del":
expression=expression[:-1]
elif event=="C":
expression=""
window.Element("result").update("")
elif event == "x":
expression+="*"
elif event == "^":
expression+="**"
elif event =="÷":
expression+="/"
elif event=="+/-":
expression="-"+expression
elif event=="1/x":
expression="1/"+expression
elif event =="x^2":
expression+="**2"
elif event =="√":
expression+="**(0.5)"
else:
expression+=event
# 在界面上显示
window.Element("expression").update(expression)
window.close()