云计算百科
云计算领域专业知识百科平台

Qt计算器开发:从零实现四则运算

Qt 作为跨平台的 C++ 图形界面开发框架,凭借其简洁的 API 和强大的信号槽机制,非常适合开发桌面应用。本文将手把手教你实现一个具备基础四则运算(加减乘除)、清空、退格功能的计算器,涵盖 Qt 界面布局、样式美化、信号槽绑定、表达式解析等核心知识点。

一、项目整体结构

本次开发的计算器项目包含 3 个核心文件,职责分工清晰:

文件名称作用
calculator.h 计算器类的头文件,定义类结构、成员变量和槽函数声明
calculator.cpp 计算器类的实现文件,完成界面初始化、样式美化、逻辑处理
main.cpp 程序入口,创建应用程序对象并显示计算器窗口

二、核心开发步骤

步骤 1:头文件设计(calculator.h)

首先定义Calculator类,继承自QWidget(Qt 基础窗口类),核心包含:

  • 成员变量:显示框(QLineEdit)、运算表达式(QString)
  • 槽函数:处理按钮点击、清空、退格、计算逻辑
  • 私有方法:初始化界面、初始化样式表

#ifndef CALCULATOR_H
#define CALCULATOR_H

#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QGridLayout>
#include <QString>

class Calculator : public QWidget
{
Q_OBJECT // 必须添加,启用Qt信号槽机制

public:
Calculator(QWidget *parent = nullptr);
~Calculator() = default;

private slots:
// 数字/运算符按钮点击槽函数
void onButtonClicked();
// 清空显示框
void onClearClicked();
// 退格(删除最后一个字符)
void onBackspaceClicked();
// 计算结果
void onCalculateClicked();

private:
QLineEdit *m_display; // 显示输入/结果的文本框
QString m_expression; // 存储用户输入的运算表达式
// 初始化界面布局和控件
void initUI();
// 初始化控件样式表
void initStyle();
};

#endif // CALCULATOR_H

步骤 2:界面初始化(calculator.cpp – initUI 方法)

计算器界面采用QGridLayout(网格布局)实现,优势是能精准控制控件的行列位置,贴合计算器的布局特点。

核心逻辑:
  • 显示框配置:设置右对齐、只读、放大字体,禁止手动输入(仅通过按钮触发);
  • 按钮创建:按计算器布局创建数字、运算符、功能按钮;
  • 网格布局:将显示框、按钮添加到网格,设置间距和内边距;
  • 信号槽绑定:数字 / 运算符按钮绑定通用槽函数,功能按钮绑定专属槽函数。

#include "calculator.h"
#include <QDebug>
#include <QRegExp>
#include <cmath>

Calculator::Calculator(QWidget *parent)
: QWidget(parent),
m_display(new QLineEdit(this)),
m_expression("")
{
initUI(); // 初始化界面布局
initStyle(); // 初始化样式表
}

// 初始化界面:布局+控件创建+信号槽绑定
void Calculator::initUI()
{
// 1. 显示框属性配置
m_display->setAlignment(Qt::AlignRight); // 右对齐
m_display->setReadOnly(true); // 只读,禁止手动输入
m_display->setFont(QFont("微软雅黑", 18)); // 字体放大
m_display->setMinimumHeight(60); // 设置最小高度

// 2. 创建所有按钮
QPushButton *btnAC = new QPushButton("AC", this);
QPushButton *btnBack = new QPushButton("←", this);
QPushButton *btnDiv = new QPushButton("÷", this);
QPushButton *btnMul = new QPushButton("×", this);
QPushButton *btn7 = new QPushButton("7", this);
QPushButton *btn8 = new QPushButton("8", this);
QPushButton *btn9 = new QPushButton("9", this);
QPushButton *btnSub = new QPushButton("-", this);
QPushButton *btn4 = new QPushButton("4", this);
QPushButton *btn5 = new QPushButton("5", this);
QPushButton *btn6 = new QPushButton("6", this);
QPushButton *btnAdd = new QPushButton("+", this);
QPushButton *btn1 = new QPushButton("1", this);
QPushButton *btn2 = new QPushButton("2", this);
QPushButton *btn3 = new QPushButton("3", this);
QPushButton *btnEqual = new QPushButton("=", this);
QPushButton *btn0 = new QPushButton("0", this);
QPushButton *btnDot = new QPushButton(".", this);

// 3. 网格布局配置
QGridLayout *mainLayout = new QGridLayout(this);
mainLayout->setSpacing(8); // 控件间距
mainLayout->setContentsMargins(15, 15, 15, 15); // 布局内边距

// 4. 添加控件到网格(行、列、占用行、占用列)
mainLayout->addWidget(m_display, 0, 0, 1, 4); // 显示框跨4列
mainLayout->addWidget(btnAC, 1, 0);
mainLayout->addWidget(btnBack, 1, 1);
mainLayout->addWidget(btnDiv, 1, 2);
mainLayout->addWidget(btnMul, 1, 3);
mainLayout->addWidget(btn7, 2, 0);
mainLayout->addWidget(btn8, 2, 1);
mainLayout->addWidget(btn9, 2, 2);
mainLayout->addWidget(btnSub, 2, 3);
mainLayout->addWidget(btn4, 3, 0);
mainLayout->addWidget(btn5, 3, 1);
mainLayout->addWidget(btn6, 3, 2);
mainLayout->addWidget(btnAdd, 3, 3);
mainLayout->addWidget(btn1, 4, 0);
mainLayout->addWidget(btn2, 4, 1);
mainLayout->addWidget(btn3, 4, 2);
mainLayout->addWidget(btnEqual, 4, 3, 2, 1); // 等号跨2行
mainLayout->addWidget(btn0, 5, 0, 1, 2); // 0跨2列
mainLayout->addWidget(btnDot, 5, 2);

// 5. 信号槽绑定
// 数字/运算符按钮绑定通用槽函数
QList<QPushButton*> btnList = {btn0,btn1,btn2,btn3,btn4,btn5,btn6,btn7,btn8,btn9,
btnAdd,btnSub,btnMul,btnDiv,btnDot};
for (QPushButton *btn : btnList) {
connect(btn, &QPushButton::clicked, this, &Calculator::onButtonClicked);
}
// 功能按钮绑定专属槽函数
connect(btnAC, &QPushButton::clicked, this, &Calculator::onClearClicked);
connect(btnBack, &QPushButton::clicked, this, &Calculator::onBackspaceClicked);
connect(btnEqual, &QPushButton::clicked, this, &Calculator::onCalculateClicked);

// 设置窗口固定大小
this->setFixedSize(300, 400);
this->setWindowTitle("Qt计算器");
}

步骤 3:样式美化(calculator.cpp – initStyle 方法)

通过 Qt 样式表(QSS)美化控件,实现圆角、hover / 按下状态、功能按钮差异化配色,提升界面质感。

// 初始化样式表:美化显示框、按钮
void Calculator::initStyle()
{
// 显示框样式:圆角、边框、背景色
m_display->setStyleSheet(R"(
QLineEdit {
background-color: #f8f9fa;
border: 2px solid #ced4da;
border-radius: 8px;
padding-right: 10px;
color: #212529;
}
)");

// 全局按钮样式 + 差异化配色
this->setStyleSheet(R"(
QPushButton {
font: bold 16px "微软雅黑";
background-color: #e9ecef;
border: none;
border-radius: 8px;
color: #212529;
min-height: 40px;
}
QPushButton:hover { /* 鼠标悬停 */
background-color: #dee2e6;
}
QPushButton:pressed { /* 按钮按下 */
background-color: #adb5bd;
}
/* 运算符按钮:黄色系 */
QPushButton[text="+"], QPushButton[text="-"],
QPushButton[text="×"], QPushButton[text="÷"] {
background-color: #ffc107;
color: white;
}
QPushButton[text="+"]:hover, QPushButton[text="-"]:hover,
QPushButton[text="×"]:hover, QPushButton[text="÷"]:hover {
background-color: #ffca2c;
}
/* 等号按钮:绿色系 */
QPushButton[text="="] {
background-color: #28a745;
color: white;
}
QPushButton[text="="]:hover {
background-color: #20c997;
}
/* 功能按钮:红色系 */
QPushButton[text="AC"], QPushButton[text="←"] {
background-color: #dc3545;
color: white;
}
QPushButton[text="AC"]:hover, QPushButton[text="←"]:hover {
background-color: #e55353;
}
)");
}

步骤 4:业务逻辑实现(calculator.cpp)

4.1 数字 / 运算符输入(onButtonClicked)

获取点击按钮的文本,拼接成运算表达式并显示在输入框中。

// 数字/运算符按钮点击:拼接表达式并显示
void Calculator::onButtonClicked()
{
QPushButton *btn = qobject_cast<QPushButton*>(sender()); // 获取点击的按钮
if (!btn) return;
QString text = btn->text();
m_expression += text; // 拼接表达式
m_display->setText(m_expression); // 显示到输入框
qDebug() << "当前表达式:" << m_expression; // 调试输出
}

4.2 清空与退格(onClearClicked/onBackspaceClicked)
  • 清空:重置表达式和显示框;
  • 退格:删除表达式最后一个字符。

// 清空:重置表达式和显示框
void Calculator::onClearClicked()
{
m_expression.clear();
m_display->clear();
qDebug() << "已清空表达式";
}

// 退格:删除最后一个字符
void Calculator::onBackspaceClicked()
{
if (!m_expression.isEmpty()) {
m_expression.chop(1); // 移除最后一个字符
m_display->setText(m_expression);
qDebug() << "退格后表达式:" << m_expression;
}
}

4.3 运算逻辑(onCalculateClicked)

核心逻辑:解析表达式,替换 Qt 显示的×/÷为 C++ 识别的*/,通过正则匹配提取数字和运算符,执行四则运算,并处理除零错误、表达式错误等异常。

// 计算结果:解析表达式,完成加减乘除运算
void Calculator::onCalculateClicked()
{
if (m_expression.isEmpty()) return;
// 替换×为*、÷为/,适配C++运算规则
QString expr = m_expression;
expr.replace("×", "*").replace("÷", "/");
qDebug() << "解析后的运算表达式:" << expr;

// 正则匹配:数字+运算符+数字 格式(支持小数)
QRegExp regExp("(\\\\d+\\\\.?\\\\d*)\\\\s*([+\\\\-*/])\\\\s*(\\\\d+\\\\.?\\\\d*)");
if (regExp.indexIn(expr) != -1) {
double num1 = regExp.cap(1).toDouble(); // 第一个数字
QString op = regExp.cap(2); // 运算符
double num2 = regExp.cap(3).toDouble(); // 第二个数字
double result = 0.0;

// 执行运算
if (op == "+") result = num1 + num2;
else if (op == "-") result = num1 – num2;
else if (op == "*") result = num1 * num2;
else if (op == "/") {
if (qFuzzyCompare(num2, 0.0)) { // 防止除零(浮点精度处理)
m_display->setText("错误:除零");
m_expression.clear();
return;
}
result = num1 / num2;
}

// 显示结果:移除末尾多余的0和小数点
QString resText = QString::number(result, 'f', 6).remove(QRegExp("\\\\.?0+$"));
m_display->setText(resText);
// 结果作为下一次运算的初始值
m_expression = resText;
qDebug() << "运算结果:" << num1 << op << num2 << "=" << result;
} else {
m_display->setText("表达式错误");
m_expression.clear();
qDebug() << "表达式格式错误:" << expr;
}
}

步骤 5:程序入口(main.cpp)

创建 Qt 应用程序对象,实例化计算器窗口并显示,启动事件循环。

#include "calculator.h"
#include <QApplication>
#include<mainwindow.h>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Calculator w; // 计算器窗口
w.show(); // 显示窗口
w.setWindowTitle("chenchen");
MainWindow m; // 可根据需求删除,本文核心为Calculator
m.show();
return a.exec(); // 运行Qt事件循环
}

三、运行结果

赞(0)
未经允许不得转载:网硕互联帮助中心 » Qt计算器开发:从零实现四则运算
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!