学号 20212217 姓名 刘恒谦 《Python程序设计》实验二报告

课程:《Python程序设计》
班级: 2122
姓名: 刘恒谦
学号:20212217
实验教师:王志强
实验日期:2022年4月4日
必修/选修: 公选课

1.实验内容

用pysimpleGUI库编写可视化的计算器
image

之所以选用 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()函数就可以了。

其他(感悟、思考等)

使用微软计算器的时候我还发现它自带一个历史记录的功能。
其实只需用列表把每次的运算记录下来就可以了。并不复杂,于是我也做了一个。
image

这个"↺"标志其实也是跟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()

参考资料

posted on 2022-04-05 12:52  亦知亦行  阅读(111)  评论(0编辑  收藏  举报