目录
- 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-------------------------------------------------------------



















