目录
- 0 简介
- 1.设计原理
- 1.1界面设计
- 1.1.1界面基本布局
- 1.1.2 界面调整和美化
- 1.1.2 控件重命名
- 1.2 连接信号和槽
- 1.3 软件逻辑
- 1.3.1四则运算
- 1.3.2 连续运算(不完全)的原理
- 1.3.3 清屏
- 1.3.4 退格
- 1.3.5 等于
- 1.3.6 小数点
- 2.总结与拓展
0 简介
最近在学QT,总体感觉和MFC没有太大的区别,自己跟着哔哩哔哩的老师做了个简易计算器。相关资料如下:
课程链接:风骚程序员】QT游戏开发入门到实战课堂视频精讲,QT桌面应用程序开发,史上最全的QT视频教程系统,游戏开发角度讲解QT入门
项目链接:
链接:https://pan.baidu.com/s/1znbxUV1hi065Kncs814-Rw
提取码:cx9j
限于篇幅,项目创建和发布的具体方法可能会在后续的帖子中发出,敬请期待。。。
作为基础项目,并没有做过于复杂的功能。只有整数和小数的四则运算。主要内容如下所示:
1.设计原理
1.1界面设计
1.1.1界面基本布局
先拖拽Line Edit控件和Push Button控件到相应位置,然后再做细化和整理。
1.1.2 界面调整和美化
确定好控件的大致位置后,我们可以选定按钮,然后点击“栅格布局”按钮,自动调整间距。如下图所示。
然后我们可以调整按键的颜色等属性。以背景色为例
在想要改变样式的控件上方,鼠标右击菜单中选择“改变样式表”,点击“添加颜色”,选择“背景色”然后选择喜欢的颜色即可。
1.1.2 控件重命名
为了项目开发和维护方便,往往需要对控件进行重命名。所以我们在此对各个控件进行重命名。
直接点击控件,然后在属性列表中修改相应的属性即可。
1.2 连接信号和槽
由于项目比较小,所以我们将所有信号都绑定到同一个槽函数Onclicked
中进行处理。程序如下:
//绑定数字
connect(ui->pushButton_0,&QPushButton::clicked,this,[this](){Onclicked(Num, "0");});
connect(ui->pushButton_1,&QPushButton::clicked,this,[this](){Onclicked(Num, "1");});
connect(ui->pushButton_2,&QPushButton::clicked,this,[this](){Onclicked(Num, "2");});
connect(ui->pushButton_3,&QPushButton::clicked,this,[this](){Onclicked(Num, "3");});
connect(ui->pushButton_4,&QPushButton::clicked,this,[this](){Onclicked(Num, "4");});
connect(ui->pushButton_5,&QPushButton::clicked,this,[this](){Onclicked(Num, "5");});
connect(ui->pushButton_6,&QPushButton::clicked,this,[this](){Onclicked(Num, "6");});
connect(ui->pushButton_7,&QPushButton::clicked,this,[this](){Onclicked(Num, "7");});
connect(ui->pushButton_8,&QPushButton::clicked,this,[this](){Onclicked(Num, "8");});
connect(ui->pushButton_9,&QPushButton::clicked,this,[this](){Onclicked(Num, "9");});
//绑定运算符
connect(ui->pushButton_plus,&QPushButton::clicked,this,[this](){Onclicked(Op, "+");});
connect(ui->pushButton_sub,&QPushButton::clicked,this,[this](){Onclicked(Op, "-");});
connect(ui->pushButton_mul,&QPushButton::clicked,this,[this](){Onclicked(Op, "*");});
connect(ui->pushButton_div,&QPushButton::clicked,this,[this](){Onclicked(Op, "/");});
//其他按钮绑定
connect(ui->pushButton_clear,&QPushButton::clicked,this,[this](){Onclicked(Clear, "Clear");});
connect(ui->pushButton_backspace,&QPushButton::clicked,this,[this](){Onclicked(BackSpace, "BackSpace");});
connect(ui->pushButton_equ,&QPushButton::clicked,this,[this](){Onclicked(Equal , "=");});
connect(ui->pushButton_dot,&QPushButton::clicked,this,[this](){Onclicked(Dot , ".");});
1.3 软件逻辑
1.3.1四则运算
此次我们的软件功能只涉及两个数的运算,所以需要先区分算式中的两个数据
以运算符为分界,运算符之前的数据为第一个数据,之后的为第二个参与运算的数据,如下所示:
if(mOp.isEmpty())
{
mNum1 += _btn;
}
else
{
mNum2 += _btn;
}
然后就是四则运算的具体实现,这里我们封装了一个运算函数,来实现具体的功能。
void Widget::Cal_res(bool *is_right, double *res)
{
if(mNum1.isEmpty() || mNum2.isEmpty() || mOp.isEmpty())
{
*is_right = false;
*res = 0.0;
return ;
}
double num1 = mNum1.toDouble();
double num2 = mNum2.toDouble();
double result = 0;
if(mOp == '+')
result = num1 + num2;
else if(mOp == '-')
result = num1 - num2;
else if(mOp == '*')
result = num1 * num2;
else if(mOp == '/')
{
if(num2 != 0)
result = num1 / num2;
else
{
ui->lineEdit->setText("error!");
{
*is_right = 0;
*res = 0;
return ;
}
}
}
ui->lineEdit->setText(QString::number(result));
*is_right = true;
*res = result;
return ;
}
is_right
参数来反映是否得到了正确的结果,错误为false
,正确为true
;
res
参数返回具体的计算结果。
- 首先是
if
的条件判断,如果缺少数据或者运算符,此时无法计算,直接返回。 - 接下来根据具体的运算符执行相关的逻辑计算,当除数为0时终止计算,并输出
error
。 - 得到正确的计算结果,并返回。
1.3.2 连续运算(不完全)的原理
在此次项目中,我们实现了连续运算,但是并未考虑到运算符的优先级等问题,只是在进行下次运算时,自动计算上一个算式的计算结果,所以我们做了如下的处理:
if(!mNum1.isEmpty())
{
if(!mNum2.isEmpty())
{
Cal_res(&is_right, &res);
if(is_right)
{
mNum1 = QString::number(res);
mNum2.clear();
}
}
mOp = _btn;
}
也就是说,直接将上次的运算结果赋值给mNum1
,然后再执行接下来的运算。
1.3.3 清屏
清除(清屏)的逻辑比较简单,只需将数据清除,使之显示为空即可。
mNum1.clear();
mNum2.clear();
mOp.clear();
后面就是我们显示的语句:
ui->lineEdit->setText(mNum1 + mOp + mNum2);
1.3.4 退格
退格是非常常见的操作,在写错的时候可以点击退格,然后重新输入需要计算的数据或运算符。退格实现的原理如下:
if(!mNum2.isEmpty())
mNum2.chop(1);
else if(!mOp.isEmpty())
mOp.chop(1);
else if(!mNum1.isEmpty())
mNum1.chop(1);
else
return ;
由于我们的算式是mNum1+mOp+mNum2
的格式,退格是从后往前逐一删除的,所以要反向判断,如果有相关字符串5,直接将末尾的字符清除,再重新显示即可。
1.3.5 等于
等号就是计算并显示结果,而我们在前面的小节中已经阐述了核心的计算逻辑,接下来直接调用相关的接口即可:
Cal_res(&is_right, &res);
mNum1.clear();
mNum2.clear();
mOp.clear();
return ;
我们调用函数得到了相应的结果,然后再将相关的数据清零,以便进行下次计算。
1.3.6 小数点
小数点的添加就比较讲究了,我们先看看实现的具体程序:
if(mOp.isEmpty())
{
if((!mNum1.isEmpty()) && (!mNum1.contains('.')))
{
mNum1 += _btn;
}
}
else
{
if((!mNum2.isEmpty()) && (!mNum2.contains('.')))
{
mNum2 += _btn;
}
}
也就是说,先判断是否为空,如果没有位值,则小数点将没有任何意义,然后就判断该小数点应该添加的位置,然后完成添加。
2.总结与拓展
显然,这只是一个基本的小项目,还有很多功能值得开发和探索,如果有时间,还会更新后续帖子,并在一下方面做出延伸和拓展,敬请期待。。。
- 增加更换皮肤的功能
- 界面可缩放
- 连续计算时可显示整个算式
- 增加小括号运算符号
- 可保存历史(前几次)计算结果
- 增加键盘输入功能
红色部分不是必须的,但是可以提升使用体验。
蓝色部分是从计算本身的功能出发,需要做出的一些改进。
-----------------------------------------------------------END-------------------------------------------------------------