1.具体操作
首先选择20个QPushButton,设置最大最小值都为40,放置成五行四列,选择网状布局,将右下角的一个QPushButton删除,将剩下一个QPushButton的长设置成90,剩下改标签名。然后在顶部加一个QLineEdit。最后将所有对象名改成右边的形式即可。
2.最终效果展示
3.代码框架搭建
3.1在widget.h中
private:
Ui::Widget *ui;
QString expression;
};
3.2在widget.ui中
1.转到槽函数
2.选择点击函数
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.将原本的按钮标签删除掉
2.在按钮上放图片代码
//按钮上放图片
QIcon con("E:\\project\\work_01\\work\\Snipaste_2025-07-08_13-40-02.png");
ui->delButton->setIcon(con);
3.调整图片大小
这里我调整成34X34,可以根据自身要求来修改
4.最终效果展示
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. 计算流程
-
遍历表达式字符:
-
遇到数字:累加后压入
s_num(如'2''4'→24)。 -
遇到运算符:
- 若栈空或优先级更高:直接压入
s_opt。 - 否则:弹出栈顶运算符,计算并压回结果。
- 若栈空或优先级更高:直接压入
-
-
括号处理:
- 遇到
(:直接压栈。 - 遇到
):不断弹出运算符计算,直到弹出(。
- 遇到
-
优先级规则:
(>* />+ -(通过Priority()函数实现)。
3. 关键操作
-
计算时:从
s_num弹出两个数,按运算符计算后压回。- 注意顺序:后弹出的数是第一个操作数(如
5 - 3是num2(5) - num1(3))。所以我们除和减需要反过来用num2/num1,num2-num1
- 注意顺序:后弹出的数是第一个操作数(如
-
结束:表达式遍历完后,栈顶即为结果。
4. 示例:(5*6)+(24/3)-10
- 计算
5*6=30→s_num=[30] - 计算
24/3=8→s_num=[30,8] - 计算
30+8=38→s_num=[38] - 计算
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;
}
}