5.Qt实现计算器

177 阅读5分钟

1.具体操作

首先选择20个QPushButton,设置最大最小值都为40,放置成五行四列,选择网状布局,将右下角的一个QPushButton删除,将剩下一个QPushButton的长设置成90,剩下改标签名。然后在顶部加一个QLineEdit。最后将所有对象名改成右边的形式即可。

2.最终效果展示

image.png

3.代码框架搭建

3.1在widget.h中

private:
    Ui::Widget *ui;
    QString expression;
};

3.2在widget.ui中

1.转到槽函数

image.png

2.选择点击函数

image.png

4.数字按钮处理函数

4.1以0举例

void Widget::on_zeroButton_clicked() {
    expression += "0";
    ui->mainLineEdit->setText(expression);
}

4.2以1举例

//将字符串变量+1,并把他显示在行编辑文本上
void Widget::on_oneButton_clicked()
{
    expression += "1";
    ui->mainLineEdit->setText(expression);
}

依此类推,0,1,2,3,4,5,6,7,8,9,"(",")"都是这么写的

5.符号按钮处理函数

5.1以加号举例

void Widget::on_plusButton_clicked() {
    if (!expression.isEmpty()) {
        expression += "+";
        ui->mainLineEdit->setText(expression);
    }
}

5.2以减号举例

void Widget::on_minusButton_clicked() {
    if (!expression.isEmpty()) {
        expression += "-";
        ui->mainLineEdit->setText(expression);
    }
}

依此类推,+,-,*,/都是这么写的

6.清空按钮的实现

void Widget::on_clearButton_clicked()
{
    expression.clear();
    ui->mainLineEdit->clear();
}

7.删除按钮的实现

void Widget::on_delButton_clicked()
{
    expression.chop(1);
    ui->mainLineEdit->setText(expression);
}

6.设置计算器的参数

//设置计算器的大小,长为220,宽为340
this->setMaximumSize(220,340);
this->setMinimumSize(220,340);

//设置计算器的名字为Calculator,中文命名可能会有问题
this->setWindowTitle("Calculator");

//设置在行编辑显示的字体为宋体,字体大小为12
QFont f("宋体",12);
ui->mainLineEdit->setFont(f);

7.将一张图片设置成删除键图片

1.将原本的按钮标签删除掉

image.png

2.在按钮上放图片代码

//按钮上放图片
QIcon con("E:\\project\\work_01\\work\\Snipaste_2025-07-08_13-40-02.png");
ui->delButton->setIcon(con);

3.调整图片大小

这里我调整成34X34,可以根据自身要求来修改

image.png

4.最终效果展示

image.png

8.实现等于按钮

8.1在widget.h中

private:
    int Priority(char ch);
};

8.2在widget.cpp中

void Widget::on_equalButton_clicked()
{
    QStack <int>s_num, s_opt;

    char opt[128] = {0};
    int i = 0,tmp = 0, num1, num2;

    //把QString转换成char *
    QByteArray ba;
    ba.append(expression);
    strcpy(opt,ba.data());

    while(opt[i] != '\0' || !s_opt.empty())
    {
        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(s_opt.empty() || 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()))
            {
                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;
                    case '-':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num2 - num1);
                        break;
                    case '*':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num1 * num2);
                        break;
                    case '/':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num2 / num1);
                        break;
                }

            }
        }
    }
    ui->mainLineEdit->setText(QString::number(s_num.top()));
    expression.clear();
}

int Widget::Priority(char ch)
{
    switch(ch)
    {
    case '(':
        return 3;
    case '*':
    case '/':
        return 2;
    case '+':
    case '-':
        return 1;
    default:
        return 0;
    }
}

1. 核心数据结构

  • s_num:数字栈,存储运算中的数字(如 5, 6, 24)。
  • s_opt:运算符栈,存储运算符(如 +, *, ()。

2. 计算流程

  1. 遍历表达式字符

    • 遇到数字:累加后压入 s_num(如 '2''4' → 24)。

    • 遇到运算符:

      • 若栈空或优先级更高:直接压入 s_opt
      • 否则:弹出栈顶运算符,计算并压回结果。
  2. 括号处理

    • 遇到 (:直接压栈。
    • 遇到 ):不断弹出运算符计算,直到弹出 (
  3. 优先级规则

    • ( > * / > + -(通过 Priority() 函数实现)。

3. 关键操作

  • 计算时:从 s_num 弹出两个数,按运算符计算后压回。

    • 注意顺序:后弹出的数是第一个操作数(如 5 - 3 是 num2(5) - num1(3))。所以我们除和减需要反过来用num2/num1num2-num1
  • 结束:表达式遍历完后,栈顶即为结果。

4. 示例:(5*6)+(24/3)-10

  1. 计算 5*6=30 → s_num=[30]
  2. 计算 24/3=8 → s_num=[30,8]
  3. 计算 30+8=38 → s_num=[38]
  4. 计算 38-10=28 → 输出 28

9.完整代码

9.1在widget.h中

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <Qstring>
#include <QStack>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_oneButton_clicked();

    void on_twoButton_clicked();

    void on_threeButton_clicked();

    void on_fourButton_clicked();

    void on_fiveButton_clicked();

    void on_sixButton_clicked();

    void on_sevenButton_clicked();

    void on_eightButton_clicked();

    void on_nineButton_clicked();

    void on_zeroButton_clicked();

    void on_addButton_clicked();

    void on_subButton_clicked();

    void on_mulButton_clicked();

    void on_divButton_clicked();

    void on_leftButton_clicked();

    void on_rightButton_clicked();

    void on_clearButton_clicked();

    void on_delButton_clicked();

    void on_equalButton_clicked();

private:
    Ui::Widget *ui;
    QString expression;

    int Priority(char ch);
};

#endif // WIDGET_H

9.2在widget.cpp中

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //设置计算器的大小,长为220,宽为340
    this->setMaximumSize(220,340);
    this->setMinimumSize(220,340);

    //设置计算器的名字为Calculator,中文命名可能会有问题
    this->setWindowTitle("Calculator");

    //设置在行编辑显示的字体为宋体,字体大小为12
    QFont f("宋体",12);
    ui->mainLineEdit->setFont(f);

    //按钮上放图片
    QIcon con("E:\\project\\work_01\\work\\Snipaste_2025-07-08_13-40-02.png");
    ui->delButton->setIcon(con);

    //改变等于号颜色
    ui->equalButton->setStyleSheet("background:skyblue");
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_oneButton_clicked()
{
    expression += "1";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_twoButton_clicked()
{
    expression += "2";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_threeButton_clicked()
{
    expression += "3";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_fourButton_clicked()
{
    expression += "4";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_fiveButton_clicked()
{
    expression += "5";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_sixButton_clicked()
{
    expression += "6";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_sevenButton_clicked()
{
    expression += "7";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_eightButton_clicked()
{
    expression += "8";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_nineButton_clicked()
{
    expression += "9";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_zeroButton_clicked()
{
    expression += "0";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_addButton_clicked()
{
    if (!expression.isEmpty()) {
    expression += "+";
    ui->mainLineEdit->setText(expression);
    }
}


void Widget::on_subButton_clicked()
{
    if (!expression.isEmpty()) {
    expression += "-";
    ui->mainLineEdit->setText(expression);
    }
}


void Widget::on_mulButton_clicked()
{
    if (!expression.isEmpty()) {
    expression += "*";
    ui->mainLineEdit->setText(expression);
    }
}


void Widget::on_divButton_clicked()
{
    if (!expression.isEmpty()) {
    expression += "/";
    ui->mainLineEdit->setText(expression);
    }
}


void Widget::on_leftButton_clicked()
{
    expression += "(";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_rightButton_clicked()
{
    expression += ")";
    ui->mainLineEdit->setText(expression);
}



void Widget::on_clearButton_clicked()
{
    expression.clear();
    ui->mainLineEdit->clear();
}



void Widget::on_delButton_clicked()
{
    expression.chop(1);
    ui->mainLineEdit->setText(expression);
}


void Widget::on_equalButton_clicked()
{
    QStack <int>s_num, s_opt;

    char opt[128] = {0};
    int i = 0,tmp = 0, num1, num2;

    //把QString转换成char *
    QByteArray ba;
    ba.append(expression);
    strcpy(opt,ba.data());

    while(opt[i] != '\0' || !s_opt.empty())
    {
        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(s_opt.empty() || 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()))
            {
                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;
                    case '-':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num2 - num1);
                        break;
                    case '*':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num1 * num2);
                        break;
                    case '/':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num2 / num1);
                        break;
                }

            }
        }
    }
    ui->mainLineEdit->setText(QString::number(s_num.top()));
    expression.clear();
}

int Widget::Priority(char ch)
{
    switch(ch)
    {
    case '(':
        return 3;
    case '*':
    case '/':
        return 2;
    case '+':
    case '-':
        return 1;
    default:
        return 0;
    }
}