VS+QT+SQLite实现简单的计算器

  • 0. 计算器功能说明
    • 0.1 计算器界面
    • 0.2 历史记录模块
    • 0.3 总体说明
  • 1. 安装VS
    • 1.1 下载VS_Community
    • 1.2 安装VS
  • 2. 安装Qt
    • 2.1 下载Qt
    • 2.2 安装Qt
  • 3. 为VS配置Qt VS Tools
    • 3.1 下载安装Qt VS Tools
    • 3.2 配置环境变量
    • 3.3 特殊问题解决
  • 4. 安装SQLite
    • 4.1 下载SQLite
    • 4.2 安装SQLite
    • 4.3 测试SQLite
  • 5. 创建和配置VS+QT的工程
    • 5.1 创建VS工程
    • 5.2 重定向目标工具集
    • 5.3 添加main函数
    • 5.3 配置QT模块
  • 6. 搭建程序框架
    • 6.1 建立计算器的QT类
    • 6.2 在Main中实例化计算器类
    • 6.3 新建UI界面
    • 6.4 编译UI界面
    • 6.5 更换窗体的名称和标题
    • 6.6 建立计算器UI对象
  • 7. 设计UI界面
    • 7.1 Qt设计师面板介绍
    • 7.2 添加一个水平布局
    • 7.3 添加Text Browser和水平布局
    • 7.4 添加垂直布局和按钮
    • 7.5 添加菜单栏
    • 7.6 保存并运行
  • 8. 添加成员变量和函数框架
    • 8.1 添加成员变量
    • 8.2 添加成员函数框架
  • 9. 设置与数据库的连接
    • 9.1 添加数据库头文件
    • 9.2 配置与数据库的连接
  • 10. 实现槽函数功能
    • 10.1 数字按钮组槽函数
    • 10.2 操作符按钮组槽函数
    • 10.3 结果计算与存储函数
    • 10.4 单个键与菜单栏槽函数
    • 10.5 完成效果展示
  • 11. 代码总结
    • 11.1 文档版代码(纯代码)
    • 11.2 整个工程(百度网盘)
  • 12. 多多点赞关注,常交流!

0. 计算器功能说明

0.1 计算器界面

计算器界面及其模块介绍如下:

0.2 历史记录模块

点开设置按钮,有三个选项,功能如下:

我们点击查看历史,可以看到效果:

0.3 总体说明

计算器整体功能简单,就是基本的四则运算,加上存储历史记录的功能,可以用来学习QT和SQLite。

我们会使用三个软件,分别为VS+QT(提供界面UI)+SQLite(提供数据库)。

不会QT和SQLite没关系。这里不涉及很深入的知识,手把手教学,包教包会。

下面就从配置开发环境开始。

1. 安装VS

1.1 下载VS_Community

这里有VS的下载链接,自行取用:VS_Community下载

1.2 安装VS

双击VS_Community.exe,傻瓜式安装(我们只需要C++开发环境),不再详述。

2. 安装Qt

2.1 下载Qt

这里有Qt的离线安装包网址,自行取用:Qt离线安装包下载

2.2 安装Qt

双击打开qt-opensource-windows-x86-5.12-8.exe,出现欢迎界面,点 next:

登录Qt账户:

直接下一步,然后选择文件夹,这个自由选择,只要知道自己装在哪就好了。

选择安装的组件,如下:

一直下一步,直至安装完成。

3. 为VS配置Qt VS Tools

3.1 下载安装Qt VS Tools

打开VS,找到标题栏的 扩展,点击子选项 管理扩展:

在管理扩展中安装Qt VS Tools:

下载安装完成后,关闭VS的所有窗口,会自动应用更改,你只需要最后点击 “modify” 按钮确认即可。

注意: 再次打开VS有可能会出现下图错误,这时两种尝试方法:

  1. 打开VS_Community升级VS至最新版本。
  2. 卸载Qt VS Tools,重新安装,我是采用的第二种方案,解决了。

3.2 配置环境变量

之后配置环境变量,WIN+Q组合键打开搜索,键入 “编辑系统环境变量” ,选中打开:



3.3 特殊问题解决

打开VS,找到依次点击:扩展 -> Qt VS Tools -> Qt Options,VS会自动为你选中QT的msvc,如果不报错,配置完成。

注意:如果出现报错,信息显示如:The following error occured:These Qt version are inaccessible,那么需要以下操作:


重新打开 Qt Options,进行下面操作:

删除原先的Qt Version,只保留我们新添加的,然后将其设为默认:

不报错,就配置完成了。

4. 安装SQLite

4.1 下载SQLite

这里提供SQLite的组件下载地址,大家自行取用:SQLite下载

4.2 安装SQLite

将两个压缩包放到合适的位置,分别解压即可。

配置环境变量,仍旧是在Path里面,添加SQLite的路径:

4.3 测试SQLite

按下 WIN+Q 组合键打开搜索,输出 “cmd” ,然后回车,打开命令行,输入sqlite3,回车:

5. 创建和配置VS+QT的工程

5.1 创建VS工程

打开VS,点击创建新项目,找到 Qt Empty Application 项目,点击之后进入下一步:

配置项目名称和位置大家自选就好了,如下:


配置QT工程,一路默认就好了:

5.2 重定向目标工具集

现在编译程序会产生如下的报错,因为我们用的MSVC2017,版本落后,需要升级:

我们需要按照提示,重定向目标工具集,首先右击解决方案,找到重定向目标解决方案,单击即可:

出现重定向项目窗口,确定即可:

再次生成解决方案即可成功。

5.3 添加main函数

在Source Files里面添加main.cpp:

输入以下代码:

//引入Qt窗口应用程序
#include <QtWidgets/QApplication>int main(int argc, char* argv[]) {// 打开Qt应用环境QApplication a(argc, argv);// 结束Qt应用环境return a.exec();
}

这里只有Qt的基本应用环境的开启和关闭,没有生成任何界面。

5.3 配置QT模块

我们需要为项目添加QT的模块,否则连接会出错,如下:

首先右键单击项目,找到 属性,单击,进入属性配置界面:

然后在属性配置界面进行如下操作,进入模块选择界面:


选择 Core GUI SQL Widget 四个模块,点击Finish即可:


点击确定,再次编译运行,通过。

6. 搭建程序框架

6.1 建立计算器的QT类

右键单击项目,光标移到添加,点击Add Qt Class,如图:

添加一个名为CalculatorMine的类,如下:

配置类的属性:

为构造函数添加默认参数 Q_NULLPTR,否则编译会报错:


6.2 在Main中实例化计算器类

我们已经有了计算器类,那么就可以在main函数中添加它的对象。在main中添加以下代码:

 // 创建一个计算器对象CalculatorMine calculatorMine;// 运行计算器对象的界面calculatorMine.show();

添加之后的main函数如下:

运行程序,得到基本的窗口,效果如下:

6.3 新建UI界面

在资源文件夹中添加UI界面,首先右击 Resource Files,光标移到 添加,单击 新建项,如下:

然后根据提示进行配置:


Qt设计师界面会自动打开,或者你双击Resource Files下的CalculatorMine.ui也可以打开,如下:

6.4 编译UI界面

这个时候,你还查询不到ui界面的头文件,需要将ui文件编译之后得到,如下操作:


编译完成之后,在外部依赖项中有可能可以找到 ui_CalculatorMine.h 文件,找不到没事,不影响。

6.5 更换窗体的名称和标题

QT默认的窗口名称和标题为mianWindow,我们可以改为自己想要的:


重新编译CalculatorMine.ui文件。一般来说,UI界面的更改在VS中重新编译.ui文件即可生效,如果不行,重启VS即可。

6.6 建立计算器UI对象

有了UI类,我们就可以实例化计算器的UI了,在CalculatorMine.h中添加的代码如下:

下一步我们需要初始化对象,并展示其UI。更改CalculatorMine.cpp文件:

我们运行程序,可以看到效果:

7. 设计UI界面

7.1 Qt设计师面板介绍

面板功能介绍如下:

7.2 添加一个水平布局

鼠标左键点击Vertical Layout不放,将其拖放到UI界面效果栏中,如下:

调整UI界面和水平布局,使其大小合适(调整方式就是拖动边缘),效果如下:

7.3 添加Text Browser和水平布局

先添加一个Text Browser进入上一个水平布局中,可以看到其占据了所有的界面:

我们应该调整其大小,令其占据空间合适,这时候就要用到属性编辑器,操作如下:

以同样的方式编辑其显示字体的大小,把里面显示的字体调大一点,看着舒服:

拖一个水平布局进去,效果如下:

7.4 添加垂直布局和按钮

在第二个水平布局中拖入5个垂直布局,可以采用如下方式:

在每个垂直布局中分别拖入4个按钮(Push Button),效果如下:

然后我们修改按钮大小和按钮字体大小,ctrl+点击 逐个选中所有按钮,用属性编辑器:

双击按钮可以编辑按钮的显示文字,编辑成如下的效果:

VS编辑控件都需要其名称,为了方便使用,这里给所有的按钮都对应一个名字,双击其对象即可编辑,效果如下:

7.5 添加菜单栏

添加菜单,双击 “在这里输入” ,然后输入 “设置” ,回车即可,如下:


点击设置,双击 “在这里输入” ,然后输入 “查看历史” ,回车即可,如下:

重复添加 “关闭历史” ,“清除历史”。最终效果如下:


**注意:**如果不能输入汉字,可以从其他地方复制过来。

下一步仍旧是修改对象名称,便于使用,修改后的结果如下:

7.6 保存并运行

首先,使用Ctrl+S保存对界面的修改,整个界面就算设计完成了。

然后返回VS,编译CalculatorMine.ui。

最后编译运行项目,效果如下:

8. 添加成员变量和函数框架

8.1 添加成员变量

这里首先为计算器类添加我们用到的成员变量,在CalculatorMine.h的类中添加如下代码:

private:// 添加一个计算器UI的实例,UI界面的命名空间为UiUi::CalculatorMineWindow* ui;// 定义数字按钮组(numButtonGroup)和操作符按钮组(operatorButtonGroup)。按钮组内的按钮都是相似的,可以共用一个槽函数QButtonGroup* numButtonGroup;QButtonGroup* operatorButtonGroup;// 定义存储操作符(operatorChar)和操作数(storedNum)以及运算结果(resultNum)的变量QChar operatorChar;double storedNum;double resultNum;// 定义标志位,isOperatorClicked标记是否已经点击了操作符,isStoredNum标记是否有一个已经存储了一个数字bool isOperatorClicked;bool isStoredNum;// 定义输入数字限制,输入数字的数量不能超过numLimitconst int numLimit = 16;

注释应该比较清楚,添加进去的效果如下:


在这里,我们用到了QButtonGroup这个类,所以需要将其头文件包括一下,输入以下代码:

#include <QButtonGroup>

在文件中的效果如下:

之后我们需要在CalculatorMine.cpp中为成员变量作初始化,在CalculatorMine类的构造函数中添加以下代码:

 // 初始化存储变量和标志位变量isOperatorClicked = false;isStoredNum = false;storedNum = 0;resultNum = 0;// 初始化按钮组numButtonGroup = new QButtonGroup;operatorButtonGroup = new QButtonGroup;// 为数字按钮组添加按钮: 0 1 2 3 4 5 6 7 8 9numButtonGroup->addButton(ui->pushButton1, 1);numButtonGroup->addButton(ui->pushButton2, 2);numButtonGroup->addButton(ui->pushButton3, 3);numButtonGroup->addButton(ui->pushButton4, 4);numButtonGroup->addButton(ui->pushButton5, 5);numButtonGroup->addButton(ui->pushButton6, 6);numButtonGroup->addButton(ui->pushButton7, 7);numButtonGroup->addButton(ui->pushButton8, 8);numButtonGroup->addButton(ui->pushButton9, 9);numButtonGroup->addButton(ui->pushButton0, 0);// 为操作符按钮组添加按钮:+ - * / =operatorButtonGroup->addButton(ui->pushButtonAdd, 1);operatorButtonGroup->addButton(ui->pushButtonSub, 2);operatorButtonGroup->addButton(ui->pushButtonMul, 3);operatorButtonGroup->addButton(ui->pushButtonDiv, 4);operatorButtonGroup->addButton(ui->pushButtonEqual, 5);

注释是比较清楚的,其在VS中的效果如下:

8.2 添加成员函数框架

我们已经有了各种控件和所有需要的成员变量,下一步就是定义槽函数,执行按钮功能。

在CalculatorMine.h文件的CalculatorMine的类中添加以下代码:

// 定义一系列槽函数(与控件的信号连接),当点击计算器的某个键时,执行。
private slots:// 当数字按钮组中的某个键被点击时调用,用来更新textBrowser等。void NumButtonClicked(QAbstractButton*);// 当操作符按钮组中的某个键被点击时调用,用来更新textBrower和执行运算等。void OperatorButtonClicked(QAbstractButton*);// 当C按钮被点击时调用,用来清空textBrowser和各种变量。void PushButtonCClicked();// 当Del按钮被点击时调用,用来删除一个输入数字。void PushButtonDelClicked();// 当%按钮被点击时调用,用来将操作数除100。void PushButonPercentClicked();// 当+/-按钮被点击时调用,用来将操作数取负。void PushButtonReverseClicked();// 当=按钮被点击时调用,用来计算和显示结果。void PushButtonEqualClicked();// 当Point按钮被点击时调用,用来增加小数点。void PushButtonPointClicked();// 当查看历史被点击时调用,用来和数据库通信,获得历史记录并显示。void SearchHistory();// 用来清空历史显示void CloseHistory();// 用来清空数据库和显示。void ClearHistory();private:// 用来执行运算(在操作符被点击时调用),并与数据库通信,存储数据void CalculateResult();

这里的注释也是比较清楚的,看一下在VS中的效果:


函数声明之后再CalculatorMine.cpp中实现,在文件末尾添加以下代码:

void CalculatorMine::NumButtonClicked(QAbstractButton* numButton) {}void CalculatorMine::OperatorButtonClicked(QAbstractButton* operatorButton) {}void CalculatorMine::CalculateResult() {}void CalculatorMine::PushButtonCClicked() {}void CalculatorMine::PushButtonDelClicked() {}void CalculatorMine::PushButonPercentClicked() {}void CalculatorMine::PushButtonReverseClicked() {}void CalculatorMine::PushButtonEqualClicked() {}void CalculatorMine::PushButtonPointClicked() {}void CalculatorMine::SearchHistory() {}void CalculatorMine::CloseHistory() {}void CalculatorMine::ClearHistory() {}

这不需要多说,就是一个函数实现的框架,在VS中的效果如下:

最后,我们需要连接按钮信号和我们定义的槽函数,在Calculator类的构造函数中添加以下代码:

 // 连接按钮组和按钮组的槽函数numButtonGroup->connect(numButtonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(NumButtonClicked(QAbstractButton*)));operatorButtonGroup->connect(operatorButtonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(OperatorButtonClicked(QAbstractButton*)));// 连接普通按钮和他们对应的槽函数connect(ui->pushButtonC, SIGNAL(clicked()), this, SLOT(PushButtonCClicked()));connect(ui->pushButtonDel, SIGNAL(clicked()), this, SLOT(PushButtonDelClicked()));connect(ui->pushButtonPercent, SIGNAL(clicked()), this, SLOT(PushButonPercentClicked()));connect(ui->pushButtonReverse, SIGNAL(clicked()), this, SLOT(PushButtonReverseClicked()));connect(ui->pushButtonEqual, SIGNAL(clicked()), this, SLOT(PushButtonEqualClicked()));connect(ui->pushButtonPoint, SIGNAL(clicked()), this, SLOT(PushButtonPointClicked()));// 连接菜单项和他们对应的槽函数connect(ui->actionSearchHistory, SIGNAL(triggered()), this, SLOT(SearchHistory()));connect(ui->actionCloseHistory, SIGNAL(triggered()), this, SLOT(CloseHistory()));connect(ui->actionClearHistory, SIGNAL(triggered()), this, SLOT(ClearHistory()));

就是一个函数connect,用来连接信号和槽,VS中效果如下:

9. 设置与数据库的连接

9.1 添加数据库头文件

这里用到了数据库的操作,因此要引入数据库的库。在CalculatorMine.h中添加以下代码:

#include <QtSql>

在VS中的效果如下:

9.2 配置与数据库的连接

下面开始操作数据库了,在CalculatorMine的构造函数中(连接菜单项代码之前)添加以下代码:

 // 设置与数据库的连接。 数据库的类型为“QSQLITE”,即SQLite; 连接的名称为“sqliteMine”(随意设置);// 连接数据库的主机地址为:127.0.0.1,即回环地址(自己);要操作的数据库名称为 “HistoryData.db”(随意设置);// 连接的用户为root用户,使用默认密码123456QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "sqliteMine");db.setHostName("127,0,0,1");db.setDatabaseName("HistoryData.db");db.setUserName("root");db.setPassword("123456");if (!db.open()) {ui->textBrowser->setText("can't open database");}

注释挺清楚的,代码在VS中的效果如下:

10. 实现槽函数功能

所有的准备工作均已完成,下面我们就要实现按钮的功能了。

10.1 数字按钮组槽函数

我们点击一个数字按钮时,调用NumGroupClicked函数,因此在改函数中添加代码:

 // 用textShow接收显示器上的显示文本,用来执行判断等QString textShow = ui->textBrowser->toPlainText();// 如果上一个点击的是操作符按钮,那么就代表要输入第二个操作数了,此时清空显示,操作符标志置否。if (isOperatorClicked) {textShow.clear();isOperatorClicked = false;}// 如果输入的数字数量过多,那么就不能输入了,直接返回if (textShow.length() >= numLimit) {return;}// 为textShow追加按钮上的文本(0/1/2/3/4/5/6/7/8/9)textShow.append(numButton->text());// 将textShow的文本显示到计算器显示器上ui->textBrowser->setText(textShow);

代码注释比较清楚,在VS中显示其效果:


我们运行程序,在计算器的按钮面板上点击数字按钮,发现会出现相应的数字:

10.2 操作符按钮组槽函数

在OperatorButtonClicked函数中添加以下代码:

 // 如果上一个点击的也是操作符,那么替换掉,将操作符存储在operatorChar中。if (isOperatorClicked) {operatorChar = operatorButton->text().at(0);}else {// 如果已经存储的有数字,那么证明输入了两个数字,可以运算了,进行运算。if (isStoredNum) {CalculateResult();}else {// 如果没存数字,证明是第一次点击操作符,那么把显示屏上的数字存起来,这是第一个操作数QString textShow = ui->textBrowser->toPlainText();storedNum = textShow.toDouble();isStoredNum = true;}// 操作符标志位设置为真,存储操作符isOperatorClicked = true;operatorChar = operatorButton->text().at(0);}

注释挺清楚的,就不多解释了。

10.3 结果计算与存储函数

CalculateResult不是槽函数,是点击操作符需要调用的函数,添加如下代码:

 // 用textShow记录显示器界面的数字。QString textShow = ui->textBrowser->toPlainText();// 第一个操作数是存储的操作数,第二个操作时为显示屏上显示的数字。double previousNum = storedNum;double presentNum = textShow.toDouble();// 根据操作符(+/-/*/÷)的不同,对两个操作数执行不同的运算,存储到resultNum中。if (operatorChar == '+') {resultNum = previousNum + presentNum;}else if (operatorChar == '-') {resultNum = previousNum - presentNum;}else if (operatorChar == '*') {resultNum = previousNum * presentNum;}else if (operatorChar == '/') {resultNum = previousNum / presentNum;}// 计算的结果可以作为下一次计算的第一个操作数,便于连续运算。storedNum = resultNum;// 将数字转为QString类型的字符串,限制其串长度,赋值给texxtShow,显示在显示屏上。textShow = QString::number(resultNum, 'g', numLimit);ui->textBrowser->setText(textShow);// 使用连接 "sqliteMine" 连入数据库,这样就可以访问我们创建的数据库HistoryData了QSqlDatabase db = QSqlDatabase::database("sqliteMine");// 使用db初始化一个数据库操作的对象,用来对数据库进行管理QSqlQuery query(db);// 定义一个字符串,字符串内容是SQLite的命令,用于创建表。// CREATE TABLE IF NOT EXISTS :标准的SQL命令,意味着如果后面这个表名 history 不存在的话,那么创建一个新表。// history是表的名字,previousNum是第一个列的列名,double是第一列的数据类型。很清楚,一共四列。QString createTableString = "CREATE TABLE IF NOT EXISTS history(previousNum double, operator varchar, presentNum double, resultNum double)";// 执行创建表的命令,如果创建不成功,在显示器中进行提示。bool success = query.exec(createTableString);if (!success) {ui->textBrowser->setText("can't create table");}// 再次定义一个SQLite命令的字符串,用于插入一行数据。// INSERT INTO :标准的SQL命令,向后面的表 history 中插入数据。// (previousNum, operator, presentNum, resultNum) : 插入数据列的列名,可以用不一样的顺序,但是列名一定是表中的列。// VALUES('%1', '%2', '%3', '%4') : VALUES里面就是插入数据的值,这里的‘%1’等是占位符,真正的值是arg()里面的数据。QString insertDataString = QString("INSERT INTO history(previousNum, operator, presentNum, resultNum) VALUES('%1', '%2', '%3', '%4')").arg(previousNum).arg(operatorChar).arg(presentNum).arg(resultNum);// 执行插入命令,如果插入不成功,那么在显示器中进行提示。success = query.exec(insertDataString);if (!success) {ui->textBrowser->setText("can't insert data");}

注释清楚,不多解释。

10.4 单个键与菜单栏槽函数

剩下的槽函数更加简单,所以直接放代码了(都有注释):

void CalculatorMine::PushButtonCClicked() {// 清除显示器和俩标志位即可ui->textBrowser->clear();isOperatorClicked = false;isStoredNum = false;
}void CalculatorMine::PushButtonDelClicked() {// 删除显示器上的最后一个数字后再显示QString textShow = ui->textBrowser->toPlainText();if (textShow.length() == 0) {return;}textShow.chop(1);ui->textBrowser->setText(textShow);
}void CalculatorMine::PushButonPercentClicked() {// 把显示器上的数字除以100之后再显示QString textShow = ui->textBrowser->toPlainText();double percentResult = 0.01 * textShow.toDouble();textShow = QString::number(percentResult, 'g', numLimit);ui->textBrowser->setText(textShow);
}void CalculatorMine::PushButtonReverseClicked() {// 把显示器上的数字取负之后再显示QString textShow = ui->textBrowser->toPlainText();double reverseResult = -1 * textShow.toDouble();textShow = QString::number(reverseResult, 'g', numLimit);ui->textBrowser->setText(textShow);
}void CalculatorMine::PushButtonEqualClicked() {// 如果符合运算标准,执行运算操作,操作数标志位置假QString textShow = ui->textBrowser->toPlainText();if (!isStoredNum || textShow.length() == 0 || isOperatorClicked) {return;}CalculateResult();isStoredNum = false;
}void CalculatorMine::PushButtonPointClicked() {// 如果显示器上已经有了小数点,直接返回QString textShow = ui->textBrowser->toPlainText();if (textShow.length() >= (numLimit - 1) || textShow.contains('.', Qt::CaseSensitive)) {return;}// 如果显示器没有数字,那么那么就是0-1之间的小数,先加入一个0if (textShow.length() == 0) {textShow = "0";}// 给显示器的末尾添加一个小数点textShow.append('.');ui->textBrowser->setText(textShow);
}void CalculatorMine::SearchHistory() {// 我们获取的数据共有四个列,分别记录了第一个操作数、操作符、第二个操作数、计算结果。// 这里我们设置最多取200条运算记录,定义4个数组存储double previousNum[200];QString operatorChar[200];double presentNum[200];double resultNum[200];// 连接数据库,初始化数据库操作对象QSqlDatabase db = QSqlDatabase::database("sqliteMine");QSqlQuery query(db);// 定义一个SQL语句的字符串,用于获取数据库中所有的记录// SELECT * FROM: 标准的SQL命令,用于从后面的表 history 中查询所有的数据QString selectDataString = "SELECT * FROM history";// 执行查询语句,如果不成功,在显示屏上进行提示bool success = query.exec(selectDataString);if (!success) {ui->textBrowser->setText("can't get history data");}// 将获取的查询结果放入我们事先准备好的数组中。int index = 0;while (query.next()) {previousNum[index] = query.value(0).toDouble();operatorChar[index] = query.value(1).toString();presentNum[index] = query.value(2).toDouble();resultNum[index] = query.value(3).toDouble();index++;}// 将历史记录一条一条的插入到我们的显示器中,格式为 IDx:操作数1 操作符 操作数2 = 运算结果。ui->textBrowser->clear();for (int i = 0; i < index; i++) {QString historyString = QString("ID%1:  %2 %3 %4 = %5").arg(i + 1).arg(previousNum[i]).arg(operatorChar[i]).arg(presentNum[i]).arg(resultNum[i]);ui->textBrowser->append(historyString);}
}void CalculatorMine::CloseHistory() {// 直接清空显示器就好了ui->textBrowser->clear();
}void CalculatorMine::ClearHistory() {// 连接数据库,建立数据库操作对象QSqlDatabase db = QSqlDatabase::database("sqliteMine");QSqlQuery query(db);// 定义一个SQL语句的字符串,用来删除表。// DROP TABLE : 标准SQL语句,用于删除后面的表 history 。QString dropTableString = "DROP TABLE history";// 执行删除表的语句,如果未成功,在显示器上提醒。bool success = query.exec(dropTableString);if (!success) {ui->textBrowser->setText("can't clear history data");}else {ui->textBrowser->clear();}
}

不解释啦,注释好好看,肯定都看得懂,功能都是类似的。

10.5 完成效果展示

11. 代码总结

11.1 文档版代码(纯代码)

main.cpp

#include <QtWidgets/QApplication>
#include "CalculatorMine.h"int main(int argc, char* argv[]) {// 打开Qt应用环境QApplication a(argc, argv);// 创建一个计算器对象CalculatorMine calculatorMine;// 运行计算器对象的界面calculatorMine.show();// 结束Qt应用环境return a.exec();
}

CalculatorMine.h

#pragma once#include <QMainWindow>
#include <QButtonGroup>
#include <QtSql>
#include "ui_CalculatorMine.h"class CalculatorMine : public QMainWindow
{Q_OBJECTpublic:CalculatorMine(QWidget *parent = Q_NULLPTR);~CalculatorMine();// 定义一系列槽函数(与控件的信号连接),当点击计算器的某个键时,执行。
private slots:// 当数字按钮组中的某个键被点击时调用,用来更新textBrowser等。void NumButtonClicked(QAbstractButton*);// 当操作符按钮组中的某个键被点击时调用,用来更新textBrower和执行运算等。void OperatorButtonClicked(QAbstractButton*);// 当C按钮被点击时调用,用来清空textBrowser和各种变量。void PushButtonCClicked();// 当Del按钮被点击时调用,用来删除一个输入数字。void PushButtonDelClicked();// 当%按钮被点击时调用,用来将操作数除100。void PushButonPercentClicked();// 当+/-按钮被点击时调用,用来将操作数取负。void PushButtonReverseClicked();// 当=按钮被点击时调用,用来计算和显示结果。void PushButtonEqualClicked();// 当Point按钮被点击时调用,用来增加小数点。void PushButtonPointClicked();// 当查看历史被点击时调用,用来和数据库通信,获得历史记录并显示。void SearchHistory();// 用来清空历史显示void CloseHistory();// 用来清空数据库和显示。void ClearHistory();private:// 用来执行运算(在操作符被点击时调用),并与数据库通信,存储数据void CalculateResult();private:// 添加一个计算器UI的实例,UI界面的命名空间为UiUi::CalculatorMineWindow* ui;// 定义数字按钮组(numButtonGroup)和操作符按钮组(operatorButtonGroup)。按钮组内的按钮都是相似的,可以共用一个槽函数QButtonGroup* numButtonGroup;QButtonGroup* operatorButtonGroup;// 定义存储操作符(operatorChar)和操作数(storedNum)以及运算结果(resultNum)的变量QChar operatorChar;double storedNum;double resultNum;// 定义标志位,isOperatorClicked标记是否已经点击了操作符,isStoredNum标记是否有一个已经存储了一个数字bool isOperatorClicked;bool isStoredNum;// 定义输入数字限制,输入数字的数量不能超过numLimitconst int numLimit = 16;
};

CalculatorMine.cpp

#include "CalculatorMine.h"CalculatorMine::CalculatorMine(QWidget *parent): QMainWindow(parent),ui(new Ui::CalculatorMineWindow)
{// 启动我们的ui界面ui->setupUi(this);// 初始化存储变量和标志位变量isOperatorClicked = false;isStoredNum = false;storedNum = 0;resultNum = 0;// 初始化按钮组numButtonGroup = new QButtonGroup;operatorButtonGroup = new QButtonGroup;// 为数字按钮组添加按钮: 0 1 2 3 4 5 6 7 8 9numButtonGroup->addButton(ui->pushButton1, 1);numButtonGroup->addButton(ui->pushButton2, 2);numButtonGroup->addButton(ui->pushButton3, 3);numButtonGroup->addButton(ui->pushButton4, 4);numButtonGroup->addButton(ui->pushButton5, 5);numButtonGroup->addButton(ui->pushButton6, 6);numButtonGroup->addButton(ui->pushButton7, 7);numButtonGroup->addButton(ui->pushButton8, 8);numButtonGroup->addButton(ui->pushButton9, 9);numButtonGroup->addButton(ui->pushButton0, 0);// 为操作符按钮组添加按钮:+ - * / =operatorButtonGroup->addButton(ui->pushButtonAdd, 1);operatorButtonGroup->addButton(ui->pushButtonSub, 2);operatorButtonGroup->addButton(ui->pushButtonMul, 3);operatorButtonGroup->addButton(ui->pushButtonDiv, 4);operatorButtonGroup->addButton(ui->pushButtonEqual, 5);// 连接按钮组和按钮组的槽函数numButtonGroup->connect(numButtonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(NumButtonClicked(QAbstractButton*)));operatorButtonGroup->connect(operatorButtonGroup, SIGNAL(buttonClicked(QAbstractButton*)), this, SLOT(OperatorButtonClicked(QAbstractButton*)));// 连接普通按钮和他们对应的槽函数connect(ui->pushButtonC, SIGNAL(clicked()), this, SLOT(PushButtonCClicked()));connect(ui->pushButtonDel, SIGNAL(clicked()), this, SLOT(PushButtonDelClicked()));connect(ui->pushButtonPercent, SIGNAL(clicked()), this, SLOT(PushButonPercentClicked()));connect(ui->pushButtonReverse, SIGNAL(clicked()), this, SLOT(PushButtonReverseClicked()));connect(ui->pushButtonEqual, SIGNAL(clicked()), this, SLOT(PushButtonEqualClicked()));connect(ui->pushButtonPoint, SIGNAL(clicked()), this, SLOT(PushButtonPointClicked()));// 设置与数据库的连接。 数据库的类型为“QSQLITE”,即SQLite; 连接的名称为“sqliteMine”(随意设置);// 连接数据库的主机地址为:127.0.0.1,即回环地址(自己);要操作的数据库名称为 “HistoryData.db”(随意设置);// 连接的用户为root用户,使用默认密码123456QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "sqliteMine");db.setHostName("127,0,0,1");db.setDatabaseName("HistoryData.db");db.setUserName("root");db.setPassword("123456");if (!db.open()) {ui->textBrowser->setText("can't open database");}// 连接菜单项和他们对应的槽函数connect(ui->actionSearchHistory, SIGNAL(triggered()), this, SLOT(SearchHistory()));connect(ui->actionCloseHistory, SIGNAL(triggered()), this, SLOT(CloseHistory()));connect(ui->actionClearHistory, SIGNAL(triggered()), this, SLOT(ClearHistory()));
}CalculatorMine::~CalculatorMine()
{
}void CalculatorMine::NumButtonClicked(QAbstractButton* numButton) {// 用textShow接收显示器上的显示文本,用来执行判断等QString textShow = ui->textBrowser->toPlainText();// 如果上一个点击的是操作符按钮,那么就代表要输入第二个操作数了,此时清空显示,操作符标志置否。if (isOperatorClicked) {textShow.clear();isOperatorClicked = false;}// 如果输入的数字数量过多,那么就不能输入了,直接返回if (textShow.length() >= numLimit) {return;}// 为textShow追加按钮上的文本(0/1/2/3/4/5/6/7/8/9)textShow.append(numButton->text());// 将textShow的文本显示到计算器显示器上ui->textBrowser->setText(textShow);
}void CalculatorMine::OperatorButtonClicked(QAbstractButton* operatorButton) {// 如果上一个点击的也是操作符,那么替换掉,将操作符存储在operatorChar中。if (isOperatorClicked) {operatorChar = operatorButton->text().at(0);}else {// 如果已经存储的有数字,那么证明输入了两个数字,可以运算了,进行运算。if (isStoredNum) {CalculateResult();}else {// 如果没存数字,证明是第一次点击操作符,那么把显示屏上的数字存起来,这是第一个操作数QString textShow = ui->textBrowser->toPlainText();storedNum = textShow.toDouble();isStoredNum = true;}// 操作符标志位设置为真,存储操作符isOperatorClicked = true;operatorChar = operatorButton->text().at(0);}
}void CalculatorMine::CalculateResult() {// 用textShow记录显示器界面的数字。QString textShow = ui->textBrowser->toPlainText();// 第一个操作数是存储的操作数,第二个操作时为显示屏上显示的数字。double previousNum = storedNum;double presentNum = textShow.toDouble();// 根据操作符(+/-/*/÷)的不同,对两个操作数执行不同的运算,存储到resultNum中。if (operatorChar == '+') {resultNum = previousNum + presentNum;}else if (operatorChar == '-') {resultNum = previousNum - presentNum;}else if (operatorChar == '*') {resultNum = previousNum * presentNum;}else if (operatorChar == '/') {resultNum = previousNum / presentNum;}// 计算的结果可以作为下一次计算的第一个操作数,便于连续运算。storedNum = resultNum;// 将数字转为QString类型的字符串,限制其串长度,赋值给texxtShow,显示在显示屏上。textShow = QString::number(resultNum, 'g', numLimit);ui->textBrowser->setText(textShow);// 使用连接 "sqliteMine" 连入数据库,这样就可以访问我们创建的数据库HistoryData了QSqlDatabase db = QSqlDatabase::database("sqliteMine");// 使用db初始化一个数据库操作的对象,用来对数据库进行管理QSqlQuery query(db);// 定义一个字符串,字符串内容是SQLite的命令,用于创建表。// CREATE TABLE IF NOT EXISTS :标准的SQL命令,意味着如果后面这个表名 history 不存在的话,那么创建一个新表。// history是表的名字,previousNum是第一个列的列名,double是第一列的数据类型。很清楚,一共四列。QString createTableString = "CREATE TABLE IF NOT EXISTS history(previousNum double, operator varchar, presentNum double, resultNum double)";// 执行创建表的命令,如果创建不成功,在显示器中进行提示。bool success = query.exec(createTableString);if (!success) {ui->textBrowser->setText("can't create table");}// 再次定义一个SQLite命令的字符串,用于插入一行数据。// INSERT INTO :标准的SQL命令,向后面的表 history 中插入数据。// (previousNum, operator, presentNum, resultNum) : 插入数据列的列名,可以用不一样的顺序,但是列名一定是表中的列。// VALUES('%1', '%2', '%3', '%4') : VALUES里面就是插入数据的值,这里的‘%1’等是占位符,真正的值是arg()里面的数据。QString insertDataString = QString("INSERT INTO history(previousNum, operator, presentNum, resultNum) VALUES('%1', '%2', '%3', '%4')").arg(previousNum).arg(operatorChar).arg(presentNum).arg(resultNum);// 执行插入命令,如果插入不成功,那么在显示器中进行提示。success = query.exec(insertDataString);if (!success) {ui->textBrowser->setText("can't insert data");}
}void CalculatorMine::PushButtonCClicked() {// 清除显示器和俩标志位即可ui->textBrowser->clear();isOperatorClicked = false;isStoredNum = false;
}void CalculatorMine::PushButtonDelClicked() {// 删除显示器上的最后一个数字后再显示QString textShow = ui->textBrowser->toPlainText();if (textShow.length() == 0) {return;}textShow.chop(1);ui->textBrowser->setText(textShow);
}void CalculatorMine::PushButonPercentClicked() {// 把显示器上的数字除以100之后再显示QString textShow = ui->textBrowser->toPlainText();double percentResult = 0.01 * textShow.toDouble();textShow = QString::number(percentResult, 'g', numLimit);ui->textBrowser->setText(textShow);
}void CalculatorMine::PushButtonReverseClicked() {// 把显示器上的数字取负之后再显示QString textShow = ui->textBrowser->toPlainText();double reverseResult = -1 * textShow.toDouble();textShow = QString::number(reverseResult, 'g', numLimit);ui->textBrowser->setText(textShow);
}void CalculatorMine::PushButtonEqualClicked() {// 如果符合运算标准,执行运算操作,操作数标志位置假QString textShow = ui->textBrowser->toPlainText();if (!isStoredNum || textShow.length() == 0 || isOperatorClicked) {return;}CalculateResult();isStoredNum = false;
}void CalculatorMine::PushButtonPointClicked() {// 如果显示器上已经有了小数点,直接返回QString textShow = ui->textBrowser->toPlainText();if (textShow.length() >= (numLimit - 1) || textShow.contains('.', Qt::CaseSensitive)) {return;}// 如果显示器没有数字,那么那么就是0-1之间的小数,先加入一个0if (textShow.length() == 0) {textShow = "0";}// 给显示器的末尾添加一个小数点textShow.append('.');ui->textBrowser->setText(textShow);
}void CalculatorMine::SearchHistory() {// 我们获取的数据共有四个列,分别记录了第一个操作数、操作符、第二个操作数、计算结果。// 这里我们设置最多取200条运算记录,定义4个数组存储double previousNum[200];QString operatorChar[200];double presentNum[200];double resultNum[200];// 连接数据库,初始化数据库操作对象QSqlDatabase db = QSqlDatabase::database("sqliteMine");QSqlQuery query(db);// 定义一个SQL语句的字符串,用于获取数据库中所有的记录// SELECT * FROM: 标准的SQL命令,用于从后面的表 history 中查询所有的数据QString selectDataString = "SELECT * FROM history";// 执行查询语句,如果不成功,在显示屏上进行提示bool success = query.exec(selectDataString);if (!success) {ui->textBrowser->setText("can't get history data");}// 将获取的查询结果放入我们事先准备好的数组中。int index = 0;while (query.next()) {previousNum[index] = query.value(0).toDouble();operatorChar[index] = query.value(1).toString();presentNum[index] = query.value(2).toDouble();resultNum[index] = query.value(3).toDouble();index++;}// 将历史记录一条一条的插入到我们的显示器中,格式为 IDx:操作数1 操作符 操作数2 = 运算结果。ui->textBrowser->clear();for (int i = 0; i < index; i++) {QString historyString = QString("ID%1:  %2 %3 %4 = %5").arg(i + 1).arg(previousNum[i]).arg(operatorChar[i]).arg(presentNum[i]).arg(resultNum[i]);ui->textBrowser->append(historyString);}
}void CalculatorMine::CloseHistory() {// 直接清空显示器就好了ui->textBrowser->clear();
}void CalculatorMine::ClearHistory() {// 连接数据库,建立数据库操作对象QSqlDatabase db = QSqlDatabase::database("sqliteMine");QSqlQuery query(db);// 定义一个SQL语句的字符串,用来删除表。// DROP TABLE : 标准SQL语句,用于删除后面的表 history 。QString dropTableString = "DROP TABLE history";// 执行删除表的语句,如果未成功,在显示器上提醒。bool success = query.exec(dropTableString);if (!success) {ui->textBrowser->setText("can't clear history data");}else {ui->textBrowser->clear();}
}

ui_CalculatorMine.h 这个是自动生成的文件,放出来也没啥用,截图给大家认识以下:

11.2 整个工程(百度网盘)

我把编译产生的附加文件删了之后,整个工程只有10k,配置好环境后就可以直接运行,下面是资源:

链接: CalculatorMine.zip

提取码:qt6j

12. 多多点赞关注,常交流!

VS+QT+SQLite实现简单的计算器相关推荐

  1. linux qt小型计算器,Qt实现一个简单的计算器

    Qt实现一个简单的计算器 作者:hackett 微信公众号:加班猿 一.UI界面版 运行效果:输入num1和num2选择+-*/点击计算即可 UI界面设计: 3个lineEdit(lineEditNu ...

  2. 使用Qt做一个简单计算器

    title: Calculator date: 2022-09-04 11:10:12 tags: [Qt, 应用, C++] typora-root-url: Calculator 使用Qt做一个简 ...

  3. QT实现一个简单计算器

    QT实现一个简单计算器 学生一枚,水平有限,如有问题,还望指正 第一步 通过QT设计师绘制出界面图形,界面大致如下: 第二步 将保存的.ui文件转换为头文件,以便于自己创建的对象对其继承和使用 uic ...

  4. C++ Qt学习笔记 (1) 简易计算器设计

    最近开始学习c++ qt, 按照教材上的例程设计一个简易的桌面计算器: Qt是一个基于C++语言的跨平台应用程序和UI开发框架,主要包含一个类库,和跨平台开发及国际化的工具,最初由挪威的Trollte ...

  5. Qt项目一:简易计算器

    Qt项目一:简易计算器 用Qt开发简易计算器较简单,可做为初学者项目学习. #效果图 #主要代码 ##ui界面界面设计 ##准备 头文件中新建a.b分别储存数据和运算符 private:Ui::Wid ...

  6. C++/Qt框架下的简易计算器

    C++/Qt框架下的简易计算器 1.简易计算器-介绍 该项目目标是设计开发一个支持连续计算的简易计算器,通过单击按钮,输入并完成如4+5+6或5×8+16类似的各种连续计算,并将运算结果显示在输出文本 ...

  7. android实现计算器功能吗,利用Android实现一个简单的计算器功能

    利用Android实现一个简单的计算器功能 发布时间:2020-11-20 16:25:01 来源:亿速云 阅读:90 作者:Leah 今天就跟大家聊聊有关利用Android实现一个简单的计算器功能, ...

  8. python123程序设计题说句心里话_用c++写一个简单的计算器程序

    // 050305.cpp : 定义控制台应用程序的入口点. // // 050304.cpp : 定义控制台应用程序的入口点. // //四则运算 #include "stdafx.h&q ...

  9. 计算器的程序代码java_java 简单的计算器程序实例代码

    java 简单的计算器程序 实现实例: import java.awt.*; import java.awt.event.*; import javax.swing.*; public class c ...

最新文章

  1. 腾讯AI Lab发布三大核心战略,与自然科研达成战略合作
  2. 30天敏捷结果(30):提升敏捷结果
  3. eeglab中文教程系列(3)-绘制通道光谱图
  4. UseCase事件描述叙事流规范
  5. 2020-11-7( servlet)
  6. 队列链式结构C/C++实现(数据结构严蔚敏版)
  7. 树莓派okdo_创客的AK47—树莓派4正式发布,性能大幅提升,售价仅为35美元。
  8. AntD 可编辑行表格
  9. SpringBoot项目中,获取配置文件信息
  10. 机器学习 —— 概率图模型(Homework: CRF Learning)
  11. ajax一直返回 error
  12. @my_decorator
  13. 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
  14. 全面讲解在BIOS设置IDE设备的多种组合方式
  15. Window10环境下安装VMware12
  16. Excel如何计算年龄
  17. 学习经历与求职经历分享
  18. Svelte入门——Web Components实现跨框架组件复用(二)
  19. Web应用优化 - 优化切页模式
  20. python坐标转换_python 编写的经纬度坐标转换类

热门文章

  1. 薄膜电阻和厚膜电阻有什么区别?
  2. iOS 逆向编程(九 - 1)通过 USB 连接登录 iPhone 以及端口映射
  3. 加速客户的云计算之旅——亚马逊云科技日立解决方案
  4. 回顾历史_回顾美联储历史,美国货币政策是如何演变的?
  5. 为什么鲍尔默现在说要辞职?
  6. 浪潮计算机云计算,孙丕恕和他的云计算:浪潮是最中坚的力量
  7. 用于彩票3D的一个组合算法
  8. 计算机毕业设计django基于python商品比价平台
  9. iphone12里的计算机,iPhone12来了!性价比超高的11还值得买吗?
  10. (软件工程视频总结)之软件测试