目录
1.Calculator任务
完成一个具有可视化界面的计算器
gitcode地址:https://gitcode.net/m0_66808626/project
2.界面展示
计算器
3.PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 70 | 40 |
• Estimate | • 估计这个任务需要多少时间 | 20 | 23 |
Development | 开发 | 420 | 500 |
• Analysis | • 需求分析 (包括学习新技术) | 120 | 200 |
• Design Spec | • 生成设计文档 | 60 | 77 |
• Design Review | • 设计复审 | 40 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 50 | 35 |
• Design | • 具体设计 | 50 | 30 |
• Coding | • 具体编码 | 120 | 200 |
• Code Review | • 代码复审 | 50 | 60 |
• Test | • 测试(自我测试,修改代码,提交修改) | 40 | 50 |
Reporting | 报告 | 60 | 120 |
• Test Repor | • 测试报告 | 60 | 120 |
• Size Measurement | • 计算工作量 | 15 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 60 | 30 |
合计 | 1225 | 1525 |
4.解题思路描述
任务是完成一个具有可视化界面的计算器。
1.设计方法。用了python-Tkinter图形化界面设计计算器.
2.计算器功能。在基本的加减乘除的基础上加入阶乘,三角函数等功能。
3.资料查询。通过csdn查询Tkinter库的一些函数的用法
4.核心功能实现。通过字符串的运行来实现计算器的功能。
5.用PyInstaller将计算器实现GUI界面后打包成可执行exe文件
5.设计与实现过程
1.项目由python设计,采用了一个Calculator类来实现具有可视化界面的计算器。
2.窗口的建造:建立一个标题为“计算器”,窗口大小为400X400的窗口
def __init__(self):
super().__init__()
self.title("计算器")
self.geometry("400x400")
self.create_widgets()
3.计算器运算框和按钮的可视化:用Label组件来实现运算框的可视化,由于计算器的核心功能是由字符串的运算来实现的,所以运算框里使用了一个字符串变量result_var。按钮的实现是采用一个二维数组来储存要显示的按钮,然后通过循环用函数button()依次画出按钮。
def create_widgets(self):
self.result_var = tk.StringVar()
self.result_var.set("0") #置零
result_label = tk.Label(self, textvariable=self.result_var, anchor="e", font=("Arial", 24), bg="white", bd=10)
result_label.pack(fill=tk.BOTH, expand=True)
button_frame = tk.Frame(self)#在为按钮建立框架
button_frame.pack(fill=tk.BOTH, expand=True)
buttons = [
("AC", "⬅", "x!", "lg", "ln"),
("7", "8", "9", "/","sin"),
("4", "5", "6", "*", "cos"),
("1", "2", "3", "-","tan"),
("0", ".", "=", "+","x^y")
]
for i, row in enumerate(buttons):#按钮绘画
for j, button_text in enumerate(row):
button = tk.Button(button_frame, text=button_text, font=("Arial", 18), command=lambda text=button_text: self.on_button_click(text))
button.grid(row=i, column=j, sticky="news")
for i in range(5):
button_frame.columnconfigure(i, weight=1)##分布权重列
button_frame.rowconfigure(i, weight=1)#行
4.计算器按钮功能的实现:每一个按钮都对应特定的功能,button()函数中就需填入对应的函数,由于所有按钮是通过循环产生的,所以将所有功能函数化为一个。由于计算机的核心功能是通过字符串的运算来实现的,所以功能中会用到字符串的连接,字符串的删除,以及字符串与其他类型之间的转换。在本项目中字符串的运算采用的是eval()函数。
def on_button_click(self, button_text):
if button_text.isdigit() or button_text == ".":
if self.result_var.get() == "0":
self.result_var.set(button_text)
else:
self.result_var.set(self.result_var.get() + button_text)
elif button_text in "+-*/":
self.result_var.set(self.result_var.get() + " " + button_text + " ")
elif button_text == "AC":
self.result_var.set("0");
elif button_text == "⬅":
if(len(self.result_var.get()) == 1):
self.result_var.set("0")
else:
self.result_var.set(self.result_var.get()[:-1]);
elif button_text == "sin":
l = eval(self.result_var.get())*math.pi /180
result = math.sin(l)
result = round(result, 2)
self.result_var.set(str(result))
elif button_text == "cos":
l = eval(self.result_var.get()) * math.pi / 180
result = math.cos(l)
result = round(result, 2)
self.result_var.set(str(result))
elif button_text == "tan":
l = eval(self.result_var.get()) * math.pi / 180
result = math.tan(l)
result = round(result, 2)
self.result_var.set(str(result))
elif button_text == "x^y":
self.result_var.set(self.result_var.get() + " " + '**' + " ")
elif button_text == "ln":
l = eval(self.result_var.get())
result = math.log(l)
result = round(result, 2)
self.result_var.set(str(result))
elif button_text == "lg":
l = eval(self.result_var.get())
result = math.log10(l)
result = round(result, 2)
self.result_var.set(str(result))
elif button_text == "x!":
l = eval(self.result_var.get())
result = math.factorial(l)
self.result_var.set(str(result))
elif button_text == "=":
try:
result = eval(self.result_var.get())
self.result_var.set(str(result))
except:
self.result_var.set("错误")
5.由于三角函数,对数函数等结果通常是无限小数,所以采用结果保留两位小数。
result = round(result, 2)
6.用PyInstaller将python 生产 exe 储存在E:.\python\dist\Project1.exe
7.异常处理:
elif button_text == "=":
try:
result = eval(self.result_var.get())
self.result_var.set(str(result))
except:
self.result_var.set("错误")
6.程序性能改进
1.将按钮的绘画采用数组储存,循环绘画,减少了大量重复代码,使代码更通俗易懂。
7.单元测试展示
测试代码:
class ExampleTestcase(unittest.TestCase):
def test_example(self):
example = Calculator()
example.on_button_click('AC')
example.on_button_click('9')
example.on_button_click('/')
example.on_button_click('3')
example.on_button_click('=')
re = eval(example.result_var.get())
self.assertEqual(3,re)
example.on_button_click('AC')
example.on_button_click('12')
example.on_button_click('+')
example.on_button_click('9')
example.on_button_click('=')
re = eval(example.result_var.get())
self.assertEqual(21,re)
example.on_button_click('AC')
example.on_button_click('9')
example.on_button_click('-')
example.on_button_click('15')
example.on_button_click('=')
re = eval(example.result_var.get())
self.assertEqual( -6,re)
example.on_button_click('AC')
example.on_button_click('30')
example.on_button_click('sin')
re = eval(example.result_var.get())
self.assertEqual(0.5, re )
example.on_button_click('AC')
example.on_button_click('60')
example.on_button_click('cos')
re = eval(example.result_var.get())
self.assertEqual(0.5, re,)
结果:
8.心路历程与收获
-
学习了Tkinter库:在开始编写计算器之前,我需要了解Tkinter库的基本概念和用法。Tkinter是Python的标准GUI库,提供了创建窗口、按钮、文本框等GUI组件的功能。通过学习Tkinter,我可以更好地理解GUI编程的原理和流程。
-
设计界面布局:编写计算器的关键是设计用户友好的界面布局。我需要考虑如何将各种按钮、文本框和其他组件组织在一起,以便用户可以方便地进行计算操作。我可以使用Tkinter提供的各种布局管理器来自动调整组件的位置和大小,也可以手动指定每个组件的位置和大小。
-
处理用户输入:编写计算器需要能够接收用户的输入并正确处理。我需要为每个按钮添加事件处理函数,当用户点击按钮时执行相应的操作。例如,当用户点击数字按钮时,我需要将相应的数字添加到文本框中;当用户点击运算符按钮时,我需要根据当前的表达式和结果进行计算。
-
错误处理和容错:编写计算器时需要考虑错误处理和容错能力。例如,当用户输入无效的表达式或按下非法按钮时,我需要给出相应的提示信息或采取合适的措施。
-
测试和优化:完成编写后,我需要进行测试和优化以确保计算器的正确性和性能。我可以使用不同的输入测试各种功能,并修复可能的错误或性能问题。
总的来说,使用Python的Tkinter库编写一个计算器是一个有意义任务。通过这个过程,我不仅学到了GUI编程的基本知识和技巧,还提高了自己的问题解决能力和创造力。我相信这些经验将对我今后的编程学习和实践有所帮助。