目录
Gitcode项目地址
界面展示
PSP表格
解题思路描述
问题1
问题2
问题3
接口设计和实现过程
关键代码展示
性能改进
单元测试
异常处理
心得体会
这个作业要求在哪里 | https://bbs.csdn.net/topics/617294583 |
---|---|
这个作业的目标 | 完成一个具有可视化界面的计算器 |
其他参考文献 | 1.qt按钮样式_qt按钮样式表-CSDN博客 2.QT打包成一个exe文件。(多种方法)-CSDN博客 |
072103308-贺心悦 / QT-CALCULATOR · GitCode
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 15 | 15 |
Estimate | 估计这个任务需要多少时间 | 10 | 5 |
Development | 开发 | 120 | 100 |
Analysis | 需求分析 (包括学习新技术) | 180 | 240 |
Design Spec | 生成设计文档 | 15 | 20 |
Design Review | 设计复审 | 30 | 60 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 5 |
Design | 具体设计 | 180 | 200 |
Coding | 具体编码 | 180 | 265 |
Code Review | 代码复审 | 60 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 180 | 120 |
Reporting | 报告 | 60 | 90 |
Test Repor | 测试报告 | 120 | 90 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 1190 | 1280 |
选用了Qt6+vs2022联合开发,基于c++语言,设计一个可视化界面,通过点击计算器界面上的按钮输入一个表达式,通过逆波兰表达式算法算出表达式的值,输出在可视化界面上。
如何实现可视化界面和计算函数的连接。
如何美化可视化界面,修改可视化界面的颜色、形状、字体等。
如何将项目打包导出。
Qt自带了button组件,可通过设计ui界面设计按键,然后通过连接点击信号和槽函数,直接点击button就可以形成输入。
Qt自带的ui类,通过connect函数实现连接。
//Widget类
namespace Ui {
class Widget;
}
//一个连接函数案例,将divButton和实现输入一个÷符号的功能函数连接起来
connect(ui->divButton, SIGNAL(clicked()), this, SLOT(on_divButton_clicked()));
该部分实现的是按下按钮,往要计算的表达式里加入该按钮的符号,并把该符号显示在界面上,以按下按钮“1”为例。
private slots:
void on_oneButton_clicked();
void Widget::on_oneButton_clicked()
{
expression += "1";
display += "1";
ui->mainLineEdit->setText(display);
}
按下等于号,计算表达式,显示出计算结果,使用的是逆波兰表达式算法。
void Widget::on_equalButton_clicked()
{
QStack s_num;
QStack s_opt;
char opt[128] = {0};
int i = 0;
int numDigits=0;
double tmp = 0, num1, num2;
//把QString转换成char *
QByteArray ba;
ba = expression.toLatin1(); //把QString转换成QByteArray
strcpy(opt, ba.data()); //data可以把QByteArray转换成const char *
while (opt[i] != '\\0' || s_opt.empty() != true)
{
if (opt[i] >= '0' && opt[i] <= '9')
{
tmp = tmp * 10 + opt[i] - '0';
i++;
if (opt[i] < '0' || opt[i] > '9')
{
s_num.push(tmp);
tmp = 0;
}
}
else if (opt[i] == 'p') //输入π,e同理,省略
{
s_num.push(M_PI);
i++;
continue;
}
else //操作符
{
if (s_opt.empty() == true || Priority(opt[i]) > Priority(s_opt.top()) ||
(s_opt.top() == '(' && opt[i] != ')'))
{
s_opt.push(opt[i]);
i++;
continue;
}
if (s_opt.top() == '(' && opt[i] == ')')
{
s_opt.pop();
i++;
continue;
}
if (Priority(opt[i]) <= Priority(s_opt.top()) || (opt[i] == ')' && s_opt.top() != '(') ||
(opt[i] == '\\0' && s_opt.empty() != true))
{
char ch = s_opt.top();
s_opt.pop();
switch(ch)
{
//以加法为例,其他算数符省略
case '+':
num1 = s_num.top();
s_num.pop();
num2 = s_num.top();
s_num.pop();
s_num.push(num1 + num2);
break;
}
}
}
}
ui->mainLineEdit->setText(QString::number(s_num.top()));
display += '=';
ui->disLineEdit->setText(display);
expression.clear();
}
int Widget::Priority(char ch)
{
switch(ch)
//设置各符号优先级
{
case' ':
return 5;
case '(':
return 4;
case' ':
return 3;
case ' '::
return 2;
case '+':
return 1;
default:
return 0;
}
}
按钮的样式设计代,以按钮“1”为例。
//正常情况下样式
QPushButton{
font: 15pt "黑体";;
color: rgb(0, 0, 0);
background-color:rgb(255, 255, 255) ;
border-color: rgb(230, 231, 233);
border-radius: 10px;
border-style: solid;
border-width: 1px;
padding: 2px;
}
//鼠标停留在按钮上的样式
QPushButton::hover{
color: rgb(0, 0, 0);
background-color: rgb(221, 240, 255);
border-color: rgb(143, 186, 255);
}
//标按压下去的样式
QPushButton::pressed,QPushButton::checked{
color: #FFFFFF;
background-color: rgb(75, 111, 189)
}
在完成了基础四则运算的功能后,加入了三角函数,对数,幂等更多运算功能。
对于除数等于0的情况,在结果框里显示“ERROR”。
对于计算sin(π)时,会得出一个e-16数量级的数,考虑到π在运算过程中的精度可能会损失的问题,最后在答案数上进行一个判断,如果一个数趋近于0那么就视为0。
if (s_num.top() < 1.0e-10 && s_num.top() >= 0)
s_num.top() = 0;
在拿到这个任务后,上网查找了许多关于可视化实现的方法,最后基于对美观度和语言的考量选择了使用Qt(基于c++),在经过学习Qt的基础功能后开发了一个简单的计算器,再逐步的追加了更多的计算功能,并且学习了然后美化界面,对计算器界面进行了一点设计。在开发过程中发现使用c++计算表达式较为复杂,不像Python有eval函数能计算数学表达式,在最初选择语言的时候还是欠缺考虑,不过好在Qt在ui界面的设计上非常方便且好学。同时,也遇到了很多问题,尤其是程序的测试和打包,因为以前没有类似的经验,所以上网查了很多资料一直在不断的试错,这些对我的对软件工程的理解和领悟有了较大的帮助。
由于时间及能力有限,所以该计算器只能计算没有错误的数学表达式,很多细节都还没有处理,例如对错误表达式(如使用sin没加右括号)的判断和报错,不支持输入“00000”这种数字,不支持计算隐藏乘号的情况(如sin3π)等等,希望未来有机会能进一步做优化。总之,这次的作业让我体验了完整的项目开发流程,我会将在这个项目中得到的经验总结并加以运用到未来的项目中去,不断提高自己的能力。