Qt 桌面计算器项目

一、项目概述

在学习 Qt 桌面开发的过程中,计算器项目是经典的入门实战项目,既能巩固 Qt 核心机制,又能快速实现可视化效果。本文将完整记录一款支持四则运算、括号运算、界面美化的 Qt 计算器项目,从 UI 设计、逻辑实现、问题排查到打包发布,全程可复现,适合 Qt 入门学习与面试项目展示。

技术栈

  • 开发语言:C++
  • 开发框架:Qt 5.8.0(Qt Widgets 模块)
  • 构建工具:qmake
  • 开发环境:Qt Creator
  • 核心技术:信号与槽、QString 字符串处理、UI 布局、QSS 样式美化、表达式解析

项目功能

  • 0-9 数字、小数点输入
  • 加减乘除四则运算、括号优先级运算
  • 清零、退格、等于计算功能
  • 现代化 UI 美化(圆角按钮、hover 效果、主题配色)
  • 窗口标题自定义、字体样式设置

项目展示


二、项目开发流程

1. 新建项目与 UI 设计

(1)新建 Qt Widgets 项目

打开 Qt Creator,选择「Application → Qt Widgets Application」,项目名命名为NiceCalculator,基类选择QWidget,完成项目创建。

(2)UI 界面布局

双击widget.ui进入 Qt Designer 设计界面,按以下步骤完成布局:

  1. 顶部添加 1 个QLineEdit作为输入显示框,设置objectNamelineEdit,勾选readOnly(只读,禁止手动输入),设置右对齐显示。
  2. 下方添加 19 个QPushButton,按计算器布局排列,按钮objectName统一规范命名:
    • 数字:btn0~btn9btnDot(小数点)
    • 运算符:btnAdd(+)、btnSub(-)、btnMul(*)、btnDiv(/)、btnLeft(()、btnRight())
    • 功能键:btnClear(清空)、btnDel(删除)、btnEqual(等于)
  3. 全选按钮,右键选择「Layout → Grid Layout」自动排版,选中整个窗口右键「Lay Out Vertically」,实现界面自适应。

2. 核心代码实现

(1)头文件widget.h

定义类、槽函数与成员变量,声明所有按钮的点击事件:

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QString>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

// 数字按钮槽函数
private slots:
    void on_btn0_clicked();
    void on_btn1_clicked();
    void on_btn2_clicked();
    void on_btn3_clicked();
    void on_btn4_clicked();
    void on_btn5_clicked();
    void on_btn6_clicked();
    void on_btn7_clicked();
    void on_btn8_clicked();
    void on_btn9_clicked();
    void on_btnDot_clicked();

// 运算符按钮槽函数
    void on_btnAdd_clicked();
    void on_btnSub_clicked();
    void on_btnMul_clicked();
    void on_btnDiv_clicked();
    void on_btnLeft_clicked();
    void on_btnRight_clicked();

// 功能按钮槽函数
    void on_btnClear_clicked();
    void on_btnDel_clicked();
    void on_btnEqual_clicked();

private:
    Ui::Widget *ui;
    QString expression; // 存储用户输入的表达式
};

#endif // WIDGET_H
(2)源文件widget.cpp

实现按钮逻辑、界面初始化、表达式计算与 UI 美化:

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QScriptEngine>
#include <QFont>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 窗口基础设置
    setWindowTitle("cmh计算器");
    setFixedSize(340, 460); // 固定窗口大小,禁止拉伸

    // 输入框字体设置
    QFont f("Microsoft YaHei", 22, QFont::Bold);
    ui->lineEdit->setFont(f);
    ui->lineEdit->setAlignment(Qt::AlignRight);

    // QSS全局样式美化
    this->setStyleSheet(R"(
        QWidget { background:#f5f7fa; }
        QLineEdit {
            border:none; border-radius:12px;
            padding:16px; background:#fff;
            margin-bottom:10px;
        }
        QPushButton {
            font-size:16px; border:none;
            border-radius:18px; background:#fff;
            min-height:45px;
        }
        QPushButton:hover { background:#e6e8ed; }

        QPushButton#btnClear,QPushButton#btnDel{
            background:#ff7878; color:white;
        }
        QPushButton#btnClear:hover,QPushButton#btnDel:hover{
            background:#ff5252;
        }

        QPushButton#btnEqual{
            background:#4285F4; color:white; font-weight:bold;
        }
        QPushButton#btnEqual:hover{
            background:#3367D6;
        }
    )");
}

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

// 数字按钮点击逻辑:拼接表达式
void Widget::on_btn0_clicked() { expression += "0"; ui->lineEdit->setText(expression); }
void Widget::on_btn1_clicked() { expression += "1"; ui->lineEdit->setText(expression); }
void Widget::on_btn2_clicked() { expression += "2"; ui->lineEdit->setText(expression); }
void Widget::on_btn3_clicked() { expression += "3"; ui->lineEdit->setText(expression); }
void Widget::on_btn4_clicked() { expression += "4"; ui->lineEdit->setText(expression); }
void Widget::on_btn5_clicked() { expression += "5"; ui->lineEdit->setText(expression); }
void Widget::on_btn6_clicked() { expression += "6"; ui->lineEdit->setText(expression); }
void Widget::on_btn7_clicked() { expression += "7"; ui->lineEdit->setText(expression); }
void Widget::on_btn8_clicked() { expression += "8"; ui->lineEdit->setText(expression); }
void Widget::on_btn9_clicked() { expression += "9"; ui->lineEdit->setText(expression); }
void Widget::on_btnDot_clicked() { expression += "."; ui->lineEdit->setText(expression); }

// 运算符按钮点击逻辑
void Widget::on_btnAdd_clicked() { expression += "+"; ui->lineEdit->setText(expression); }
void Widget::on_btnSub_clicked() { expression += "-"; ui->lineEdit->setText(expression); }
void Widget::on_btnMul_clicked() { expression += "*"; ui->lineEdit->setText(expression); }
void Widget::on_btnDiv_clicked() { expression += "/"; ui->lineEdit->setText(expression); }
void Widget::on_btnLeft_clicked() { expression += "("; ui->lineEdit->setText(expression); }
void Widget::on_btnRight_clicked() { expression += ")"; ui->lineEdit->setText(expression); }

// 清空按钮
void Widget::on_btnClear_clicked()
{
    expression.clear();
    ui->lineEdit->clear();
}

// 退格按钮
void Widget::on_btnDel_clicked()
{
    expression.chop(1);
    ui->lineEdit->setText(expression);
}

// 等于按钮:表达式计算
void Widget::on_btnEqual_clicked()
{
    QScriptEngine eng;
    QScriptValue val = eng.evaluate(expression);

    // 异常处理:表达式错误提示
    if(eng.hasUncaughtException()){
        ui->lineEdit->setText("Error");
        expression.clear();
    }else{
        // 显示结果,支持连续运算
        expression = val.toString();
        ui->lineEdit->setText(expression);
    }
}
(3)项目配置文件NiceCalculator.pro

添加script模块依赖,支持QScriptEngine表达式计算:

cpp 复制代码
QT       += core gui widgets script

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

SOURCES += \
    main.cpp \
    widget.cpp

HEADERS += \
    widget.h

FORMS += \
    widget.ui

三、项目难点与踩坑总结

1. 编译报错:'QString' does not name a type

问题原因 :头文件未包含 <QString>,或类名拼写错误(写成 Qstring 小写 s)。解决方案 :在 widget.h 中添加 #include <QString>,确保类名 QString 大小写正确。

2. 编译报错:QScriptEngine: No such file or directory

问题原因 :Qt 5 中 QScriptEngine 属于 script 模块,未在 .pro 文件中添加依赖。解决方案 :在 .pro 文件中添加 QT += script,执行 qmake 后重新编译。

3. 编译报错:stray '\357' in program

问题原因 :代码中混入了中文全角空格 / 不可见字符,导致编译器语法解析失败。解决方案:删除问题行,使用英文半角输入法重新输入,全程切换英文输入法编写代码。

4. 窗口标题修改不生效

问题原因 :代码中 setWindowTitle 优先级高于 UI 中的 windowTitle 属性,代码覆盖了 UI 设置。解决方案 :二选一修改,要么在 UI 中修改 windowTitle,要么在代码中修改,避免冲突。

5. 中文乱码问题

问题原因 :源文件编码非 UTF-8,导致中文显示乱码。解决方案 :在 Qt Creator 中设置文件编码为 UTF-8,代码中使用 QString::fromUtf8("中文") 包裹中文。


四、项目总结与收获

项目收获

  1. 掌握 Qt 核心机制:深入理解了 Qt 信号与槽、事件驱动编程、UI 布局等核心概念,熟悉了 Qt 项目的完整开发流程。
  2. 提升 C++ 编程能力:通过字符串处理、表达式计算、异常处理等逻辑,强化了 C++ 基础编程能力。
  3. 学会界面开发与美化:掌握了 Qt Designer 可视化布局、QSS 样式表美化、自定义图标等界面开发技巧。
  4. 培养问题排查能力:通过解决编译报错、逻辑 bug 等问题,提升了代码调试和问题排查能力。

后续优化方向

  • 支持负数运算,增加科学计算器功能(开方、平方、三角函数等)
  • 增加历史记录查询、表达式编辑功能
  • 适配深色模式、多主题切换
  • 打包为单文件 exe,提升分发便捷性
相关推荐
用户8055336980318 小时前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner19 小时前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner9 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner9 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00612 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术12 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript