软件工程作业1——简单可视化计算器
作业基本信息
这个作业属于哪个课程 | https://bbs.csdn.net/forums/ssynkqtd-05 |
---|---|
这个作业要求在哪里 | https://bbs.csdn.net/topics/617294583 |
这个作业的目标 | 完成一个具有可视化界面的计算器) |
完成人
由于最近csdn上改过id30天不能重新修改,故学号姓名如下:
102101221 zyf
Git项目地址
界面展示
PSP表格
PSP | Persona Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 20 |
• Estimate | • 估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 500 | 540 |
• Analysis | • 需求分析 (包括学习新技术) | 35 | 30 |
• Design Spec | • 生成设计文档 | 45 | 45 |
• Design Review | • 设计复审 | 60 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 60 | 60 |
• Design | • 具体设计 | 90 | 120 |
• Coding | • 具体编码 | 100 | 120 |
• Code Review | • 代码复审 | 50 | 60 |
• Test | • 测试(自我测试,修改代码,提交修改) | 60 | 75 |
Reporting | 报告 | 40 | 35 |
• Test Repor | • 测试报告 | 15 | 10 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 15 | 15 |
合计 | 570 | 595 |
解题思路描述
要求为实现一个具有图形化界面的计算器,在实现普通的加减乘除四则运算的基础上,进一步实现科学计算器的相关内容,包括次方、幂、三角函数等相关操作。
问题1:图形化界面的实现。首先是要求图形化界面,本人选择graphics库进行py图形化设计,graphics库的重要函数的各个方法与具体内容详见link
问题2:计算器算法的实现:python中的eval函数是可以自动识别字符串并且返回字符串计算式的结果的,所以只要把click进计算器的(等号、清零、backspace等具有交互性的命令除外)统统放进string中然后让eval自己算直接return回一个得数就好了
接口设计和实现过程
首先用eval写出计算函数,其次由于graphics的局限性,需要优先考虑按键的各个单元及其在总窗口的占比,然后再考虑字体,字体方面由于库没有文本右对齐功能,需要自己写一个右对齐函数并且计算出其在结果框内所在的位置,并且把text嵌套进按键中,最后在主函数里把计算函数与接收到的windows文本进行整合计算。
关键代码展示
def jisuan(t):
middle = ''
i = 0
while i < len(t):
wd_2 = t[i:i + 2]
wd_3 = t[i:i + 3]
wd_4 = t[i:i + 4]
if (wd_2 == 'ln' or wd_3 == 'sin' or wd_3 == 'cos' or wd_3 == 'tan' or wd_3 == 'log' or wd_4 == 'asin' or wd_4 == 'acos' or wd_4 == 'atan' or wd_4 == 'sqrt'):
level = 1
if (wd_2 == 'ln'):
level = 2
elif (wd_3 == 'sin' or wd_3 == 'cos' or wd_3 == 'tan' or wd_3 == 'log'):
level = 3
elif (wd_4 == 'asin' or wd_4 == 'acos' or wd_4 == 'atan' or wd_4 == 'sqrt'):
level = 4
if (level == 3):
if (wd_3 == 'log'):
middle = middle + 'math.log'
if (wd_3 == 'sin'):
middle = middle + 'math.sin'
if (wd_3 == 'cos'):
middle = middle + 'math.cos'
if (wd_3 == 'tan'):
middle = middle + 'math.tan'
if (level == 4):
if (wd_4 == 'sqrt'):
middle = middle + 'math.sqrt'
if (wd_4 == 'asin'):
middle = middle + 'math.asin'
if (wd_4 == 'acos'):
middle = middle + 'math.acos'
if (wd_4 == 'atan'):
middle = middle + 'math.tan'
i += level
else:
middle += t[i]
i = i + 1
result = eval(middle)
list(t).clear()
list(middle).clear()
list(t).append(str(result))
return result
按钮代码
class Button:
def __init__(self,width = None,height = None, x = None, y = None, text = None,color1 = None,color2 = None):
self.width = width
self.height = height
self.x = x
self.y = y
self.text = text
self.color1 = color1#按键颜色
self.color2 = color2#窗口颜色
self.st = graphics.Point(x,y) #基础坐标点
p1 = self.st.clone()
p2 = self.st.clone() #按钮的对角线点
p1.move(-self.width / 2, -self.height / 2)
p2.move(self.width / 2, self.height / 2)#p1p2左下右上位移形成对角线
#这种设置的优点为st为中心点 可以把文本放在st点上
self.sq = graphics.Rectangle(p1, p2)#形成矩形 graphics的具体操作请参考
# https://blog.csdn.net/qq_45940395/article/details/111704989的具体内容
self.sq.setFill(color1)#填充色
self.sq.setOutline(color2)#边框色
self.square_text = graphics.Text(self.st,self.text)
def show(self,win):
self.sq.draw(win)
self.square_text.draw(win)
def change(self,color):#按键反馈
self.sq.setFill(color)
time.sleep(0.20)
self.sq.setFill(self.color1)
def click_co(self,p,color):#点击
s1 = self.sq.getP1()
s2 = self.sq.getP2()#返回矩形对角点
if p.getX() >= s1.getX() and p.getX() <= s2.getX():
if p.getY() >= s1.getY() and p.getY() <= s2.getY():
return self.text
文本代码
class text:
def __init__(self,x=None, y=None, text=None, size=None, pianyi=None):
self.x = x
self.y = y
self.text = text#数据
self.txt = text#数据计算
self.size = size #字体大小
self.pianyi = pianyi
self.pianyi_size = 0#偏移数
self.st = graphics.Point(x, y)
self.cr = graphics.Text(self.st, text)
self.cr.setSize(size)
def show(self,win):
self.cr.draw(win)
#右对齐
def gx(self, g, s): # 更改偏移量
if g == True:
self.pianyi_size += s
self.cr.move(-(self.pianyi) * s, 0)
else:
self.pianyi_size -= s
if self.pianyi_size < 0:
self.pianyi = 0
self.cr.move((self.pianyi) * s, 0)
self.cr.setText(self.text)
性能改进
可以作出如下功能的添加:
1.本计算器得出结果后输入的计算式会消失,所以优化可视化功能对计算器进行更直白的视觉优化,计算式会以浅色的状态置于计算式上方而非消失
2.通过堆栈来实现查询历史记录等功能使计算器更加方便
3.针对计算器的算法实现:针对在操作框上进行连续计算的问题,本人首先想到的就是类似于递归一样的层层向上的模式:先把所有想要实现的计算都列举出来,按照计算顺序排列(例如计算顺序:幂运算大于乘法大于加法),然后将每个计算函数内都执行本次计算次序的上一次序函数(例如乘法函数里面就要执行一次幂运算函数),这样就可以保证连续运算的可行了,但是这样设计忽略了括号内算式先算的原则(当然也可以不设计括号),所以本人又想到了堆栈的方法,但堆栈实现括号匹配的代码量又有点庞大,所以还是放弃了这个想法。后来舍友说eval可以直接暴力解决str类型的计算式问题,这才运用了eval返回result的版本。
单元测试
本次测试对 加法、cos三角函数、连乘连除进行测试,测试代码如下
import unittest
from calculation import jisuan
class TestCalculation(unittest.TestCase):
def test_add(self):
t = ["1","+","1"]
result = jisuan(t)
self.assertEqual(result, 2)
def test_cos(self):
t = "cos(1)"
result = jisuan(t)
self.assertEqual(result, 0.5403023058681398)
def test_mulanddev(self):
t = "3*5/3"
result = jisuan(t)
self.assertEqual(result,5)
测试结果如下:
心得体会
通过本次实践,首次完整的做出了一个可视化的功能物品,初步体会了可视化代码的编写,提升了代码能力,同时看到了自己代码量的不足,同时与各位同学大佬交流我也获得了很多剑走偏锋、本人绝对想不出来的实现方法和实现技巧,对我的个人能力有很大帮助。