高效学 C++|编程实例之计算器

news2024/12/23 8:47:00

 本节将实现一个能进行实数间加、减、乘、除运算的简易计算器。首先创建一个基于QWidget带界面的Qt项目,然后按照如下步骤进行操作:

01、计算器界面设计

在界面中拖入两个单行文本框和十七个按钮,按钮上显示的文字、按钮对象和单行文本框对象名如图1所示。为了美观起见,设置窗口为“栅格布局”以对齐部件。

将窗口对象的“windowTitle”属性设置为“计算器”;勾选掉第一个单行文本框(lineEdit_Show对象)的“enable”属性,使得该单行文本框变为灰色(该文本框仅用于显示结果);勾选上第二个单行文本框(lineEdit_Input对象)的“readOnly”属性(限制用户不能直接在文本框中通过键盘输入内容)、将其的“alignment”水平属性设置为“ALignRight”。

■ 图1 计算器界面设计

02、计算器功能实现

进行算术运算时,之前输入的左操作数和操作符需存储(右操作数可直接从文本框lineEdit_Input中读取),因此在自定义窗口Widget类中添加私有数据成员如下:

QString operandStr1; //用于存储字符串形式的左操作数
QString operatorStr; //用于存储操作符

并在Widget类的构造函数体中添加如下语句以将它们初始化为空串:

operandStr1="";
operatorStr="";

接下来实现点击各个按钮时触发的功能:给每个按钮的clicked()信号都添加自关联槽。以按钮1为例,自关联槽实现代码如下:

void Widget::on_btn_1_clicked()
{
  ui->lineEdit_Input->setText(ui->lineEdit_Input->text()+"1");
}

按钮2到9的功能实现和按钮1是类似的,只需把上述代码中的字符"1"改成对应的数字字符即可。对于按钮0,由于一般不会出现诸如“00”形式的数字“0”,因此代码中对这种情况进行了处理,自关联槽定义如下:

void Widget::on_btn_0_clicked()
{
if(ui->lineEdit_Input->text()!="0")
ui->lineEdit_Input->setText(ui->lineEdit_Input->text()+"0");
}

小数点按钮需要考虑按下时前面没有数字的情形(此时默认为整数部分为0)、按下时串中已有了小数点的情形,最终自关联槽定义如下:

void Widget::on_btn_Point_clicked()
{
if(ui->lineEdit_Input->text()=="")
ui->lineEdit_Input->setText("0.");
else if(ui->lineEdit_Input->text().contains(".")==true)
; //数字串中已有小数点,不能再输入
else
ui->lineEdit_Input->setText(ui->lineEdit_Input->text()+".");
}

clear按钮点击时,只需将文本框lineEdit_Input中的内容清空即可,代码如下:

void Widget::on_btn_clear_clicked()
{
ui->lineEdit_Input->clear();
}

加、减、乘、除按钮的实现是类似的。以加法按钮为例:分情况进行处理,如果按下时文本框中lineEdit_Input是空串则不进行任何处理直接结束;否则说明用户提供了一个操作数,接下来判断它是左操作数还是右操作数;若operandStr1为空说明文本框中是左操作数,将其存储到operandStr1、将运算符“+”存储到operatorStr、将文本框清空以待用户再次输入右操作数、将已输入的内容显示于文本框lineEdit_Show中;若operandStr1不为空说明文本框中已是右操作数,此时按下加号和按下等号作用是相同的,直接调用点击等号按钮关联的槽函数on_btn_Calc_clicked进行处理即可。实现代码如下:

void Widget::on_btn_Add_clicked()
{
if(ui->lineEdit_Input->text()=="") //没有输入数据
return;
else if(operandStr1=="") //没有左操作数
{
operandStr1=ui->lineEdit_Input->text();
operatorStr="+";
ui->lineEdit_Input->clear();//输入文本框清空,以待输右操作数
ui->lineEdit_Show->setText(operandStr1+operatorStr);
}
else
on_btn_Calc_clicked();
}

其它三个运算符的实现是一样的,只需将上述代码中赋值给operatorStr的字符串改成相应的运算符即可。

最后是等号按钮的实现,代码如下:

void Widget::on_btn_Calc_clicked()
  {
if(operandStr1!=""&&ui->lineEdit_Input->text()!=""&&operatorStr!="")
{
  double result;
  double operand1=operandStr1.toDouble();
  double operand2=ui->lineEdit_Input->text().toDouble();
  if(operatorStr=="+")
  result=operand1+operand2;
  else if(operatorStr=="-")
  result=operand1-operand2;
  else if(operatorStr=="*")
  result=operand1*operand2;
  else if(operatorStr=="/")
  if(operand2!=0.0)
  result=operand1/operand2;
  else
  {
  QMessageBox::warning(this,"提示","除数不能为零");
  result=0;
  }
  ui->lineEdit_Show->setText(QString::number(result));
  operandStr1=""; //计算完毕,操作数清空
  operatorStr=""; //计算完毕,操作符清空
  ui->lineEdit_Input->clear(); //计算完毕,数据输入文本框清空
    }
}

首先判断左右操作数和运算符都存在,然后将QString字符串形式的操作数转换为double类型的操作数,由QString类的成员函数toDouble实现;然后再根据运算符的不同分别进行不同的计算,结果放在result中;对于除法,代码中添加了对除数为0时的出错处理;最后将算得的结果显示在文本框lineEdit_Show中(QString的静态成员函数number用于将给定的参数转换为字符串形式),并清空相关数据以等待下一次计算。

上述代码中使用到了QMessageBox类,因此还需在widget.cpp文件中添加头文件:

#include<QMessageBox>

到此功能已全部实现,运行程序可查看效果。图3-33的左图为输入了按下按钮“2”、“3”、“+”之后的效果,右图为再按下按钮“5”、“.”、“1”、“=”之后的效果。

 ■ 图2 计算器运行效果示例

03、登陆界面设计

接下来,考虑在上述已实现计算器的基础上添加一个登陆的功能:程序运行时首先显示一个登陆界面,只有当输入了正确的用户名和密码后,才能打开计算器。

实际上,除了可以在项目创建向导中给应用程序主窗口选择“使用界面”外,在项目中新增自定义C++窗口(或部件)类时,也可以使用界面。接下来在项目中添加一个带界面的登陆对话框类,操作步骤如下:

在项目名处右单击,弹出的菜单中选择“AddNew…”,打开如图3所示的界面。选中“Qt”下的Qt设计师界面类,以创建一个Qt设计师界面类。

■ 图3 选择创建Qt设计师界面类

点击图3的 “Choose…”按钮后进入到选择界面模板的步骤,见图4。所谓“选择界面模板”,是指准备在哪种窗口(或部件)的基础上进行更多的设计(即选择窗口或部件类型做为自定义窗口类的基类),本文中选择“DialogwithoutButtons”,即使用QDialog类作为基类。

 ■ 图4 选择界面模板

点击“下一步”,进入图5所示界面。在类名文本框中填入自定义登陆对话框类的名字(本文使用“LoginDialog”),下方会自动生成相关的头文件、源文件和界面文件的名字,也可以修改这些文件的文件名(但不建议修改)以及默认以当前工程目录为存放路径。

■ 图5 设置自定义登陆对话框类的类名

再次点击“下一步”,完成带界面自定义登陆对话框类的初始创建。可以看到,工程中已新增了三个与该类有关的文件。

双击“logindialog.ui”文件打开界面设计师。将对话框窗口标题(windowTitle属性)设置为“登陆”;然后往窗口中拖入两个标签、一个按钮和两个单行文本框;标签和按钮显示的文字如图6所示,各部件的名字见图中的对象浏览器窗口。

 ■ 图6 登陆对话框界面设计

设置标签为右对齐(alignment属性:“AlignRight”);设置密码文本框的echoMode为“Password”,使得输入数据时显示为表示密码的黑色圆点;将窗口设置为“栅格布局”以方便的对齐各个部件;为了方便用户使用,还可指定部件的Tab键顺序、设置标签的快捷键及和单行文本框的伙伴关系。

04、登陆功能的实现

首先给登陆对话框类添加一个信号,在类定义中(logindialog.h文件)添加代码如下:

signals:
void LoggedIn();

 然后给“登陆”按钮的clicked()信号添加自关联槽,代码实现如下:

void LoginDialog::on_loginBtn_clicked()
{
if(ui->userEdit->text()=="admin"&&ui->pwdEdit->text()=="123456")
{
emit(LoggedIn());
hide(); //隐藏登陆窗口
}
else
QMessageBox::information(this, "提示",
                            "用户名和密码错误");
}

当输入了正确的用户名和密码时将发射LoggedIn信号(目的是通知计算器窗口把自己显示出来,信号槽关联在随后的主函数中),然后将登录对话框隐藏;否则提示用户名和密码出错。

在logindialog.cpp文件中还需添加如下头文件:

#include<QMessageBox>

为了实现先显示登陆界面,成功后再显示计算器界面的操作,以及将登陆对话框发射的LoggedIn信号和计算器窗口的显示槽函数show进行关联,主函数也需要进行修改,代码如下:

#include "widget.h"
#include <QApplication>
#include "logindialog.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

Widgetw;
    LoginDialog login(&w);
    login.show();
    QObject::connect(&login,SIGNAL(LoggedIn()),&w,SLOT(show()));

    return a.exec();
}

运行时,首先会显示出图7所示的登陆界面。在输入正确的用户名和密码、并按下登陆按钮后,才打开图1的界面。

■ 图7 登陆对话框运行效果

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/195012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

百分百拿捏offer的自动化测试面试题全套教程

最近很多咨询我&#xff0c;有没有软件测试方面的面试题&#xff0c;尤其是Python自动化测试相关的最新面试题&#xff0c;所以今天给大家整理了一份&#xff0c;希望能帮助到你们。 接口测试基础 1、公司接口测试流程是什么&#xff1f; 从开发那边获取接口设计文档、分析接口…

VUE3 指令 插槽

指令 指令是 Vue 模板语法里的特殊标记&#xff0c;在使用上和 HTML 的 data-* 属性十分相似&#xff0c;统一以 v- 开头&#xff08; e.g. v-html &#xff09;。 它以简单的方式实现了常用的 JavaScript 表达式功能&#xff0c;当表达式的值改变的时候&#xff0c;响应式地…

1x1卷积、Inception网络

目录1.1x1卷积(1x1 convolution)又称网络中的网络(network in network)池化层只能压缩图像的宽和高&#xff0c;1x1卷积能压缩通道数量&#xff0c;减少计算成本。如上图&#xff0c;输入维度的通道数为192&#xff0c;用32个1x1x192的filters&#xff0c;就能将输出的通道数压…

java基础—面试题一

文章目录1.和equals区别是什么&#xff1f;2.Java中的 <<、>>、>>> 是什么3.if-else-if-else与switch的区别4.while和do-while的区别5.switch 是否能作用在 byte 上&#xff0c;是否能作用在 long 上&#xff0c;是否能作用在String上6.&和&&…

大数据技术架构(组件)16——Hive:内置UDTF函数

1.4.11、内置UDTF函数1.4.11.1、explodeselect explode(array(100,200,300));Array<int> myCol[100,200,300][400,500,600]得到的结果如下&#xff1a;(int) myNewCol1002003004005006001.4.11.2、posexplodeselect posexplode(array(A,B,C));1.4.11.3、parse_url_tuples…

2023云原生安全值得关注的3个方向

如果说过去几年教会了我们什么的话&#xff0c;那就是云原生和开源环境中安全的重要性。 Log4j 等漏洞产生的重大影响&#xff0c;在无数的行业中浮现&#xff0c;对于云原生环境中的其他安全问题也越来越受到重视。 组织不再质疑是否要迁移到云端&#xff0c;而是在寻找最快、…

centos下安装docker 并通过docker安装gitlab

一:安装docker1、若之前安过docker&#xff0c;可以先卸载yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-selinux \docker-engine-selinux \docker-engine \docker-ce2、更新yum…

软件测试基础(四) 之 软件测试的覆盖率

一、什么是软件测试的覆盖率&#xff1f;软件测试覆盖率是软件测试技术有效性的一个度量手段&#xff0c;用来度量测试完整性。意思概括的说&#xff0c;软件测试的工作中会有非常非常多的item&#xff08;任务&#xff09;&#xff0c;执行过的任务和总任务数的一个比值&#…

尚医通 (二)项目搭建

目录一、工程结构介绍1、工程结构2、模块说明二、创建父工程1、创建sprigboot工程yygh_parent2、删除 src 目录3、配置 pom.xml4、在pom.xml中添加依赖的版本三、搭建model模块1、在父工程yygh_parent下面创建模块model2、添加项目需要的依赖3、复制项目实体类和VO类四、搭建se…

require和important区别

1.require是赋值过程&#xff0c;就是把一个值赋值给另一个&#xff0c;important是对这个值的引用 2 . require 是赋值过程并且是运行时才执行&#xff0c;也就是同步加载&#xff0c;import 是解构过程并且是编译时执行&#xff0c;理解为异步加载 3.require 的性能相对于 im…

Linux部署达梦数据库超详细教程

陈老老老板&#x1f9b8;&#x1f468;‍&#x1f4bb;本文专栏&#xff1a;国产数据库-达梦数据库&#xff08;主要讲一些达梦数据库相关的内容&#xff09;&#x1f468;‍&#x1f4bb;本文简述&#xff1a;本文讲一下达梦数据库的下载与安装教程&#xff08;Linux版&#x…

百度网盘秒传链接生成及提取方法

百度网盘秒传链接生成及提取方法 1.认识秒传链接 首先&#xff0c;我们认识一下秒传链接的格式&#xff1a; 秒传链接是由标准提取码文件名组成。例如下面的格式&#xff1a; fd00338387f50ee5919eb3df4cfce6e3#5048587008#/影视/电影/救火奶爸.mp4 百度网盘秒传链接的提取主…

FISSURE:一款功能强大的RF和逆向工程框架

关于FISSURE FISSURE是一款功能强大的RF和逆向工程框架&#xff0c;该工具适用于不同技能水平的安全研究人员&#xff0c;并提供了信号检测、信号分类、协议发现、渗透测试、IQ操作、漏洞分析、自动化和AI/机器学习等功能。该框架旨在促进软件模块、无线电、协议、信号数据、脚…

2023年怎么开通一个抖音小店?店铺开通后做什么?开店指南!

大家好&#xff0c;我是王路飞。 2023年都已经过去一个月了&#xff0c;你开通抖音小店了吗&#xff1f; 作为目前最受欢迎的创业和副业项目&#xff0c;开通抖音小店的商家数量与日俱增&#xff0c;都是为了蹭一下抖音流量的红利&#xff0c;毕竟直播带货如今正处在风口。 …

50条必背JAVA知识点(三)

31.面向对象中两个重要的概念&#xff1a;类&#xff1a;对一类事物的描述&#xff0c;是抽象的、概念上的定义对象&#xff1a;是实际存在的该类事物的每个个体&#xff0c;因而也称为实例(instance) 32.虚拟机栈&#xff0c;即为平时提到的栈结构。局部变量存储在栈结构中&a…

专利的申请和驳回

说明书和权利要求的区别 说明书里面会写这个新方案的具体内容&#xff0c;实施方案&#xff0c;解释说明等&#xff0c;权利要求书的话&#xff0c;就是对这些具体的内容进行概括 说明书应当补充说明该发明相比有技术的优势 就投屏举例: 到底怎么写 三篇 阿里 楼x投屏方法及装…

人工智能服务哪家强?IDC评估报告看过来

如果您还不知道如何选择人工智能AI服务供应商&#xff0c;那么IDC的这份评估报告也许可以派上用场。如何选择AI软件工具和平台随着科技的不断发展&#xff0c;人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;技术在近年来取得了长足的进步。从语音…

简介JWT

简介JWT http协议无状态的&#xff0c;所以需要sessionId或token的鉴权机制&#xff0c;jwt的token认证机制不需要在服务端再保留用户的认证信息或会话信息。这就意味着基于jwt认证机制的应用程序不需要去考虑用户在哪一台服务器登录了&#xff0c;这就为应用的扩展提供了便利&…

Python函数和 lambda表达式

Python提供了许多内置函数&#xff0c;比如&#xff1a;print()&#xff0c;len()等。它还支持用户自定义函数。 一、Python函数 1、函数定义使用 &#xff08;1&#xff09;函数定义 Python 允许我们将常用的代码以固定的格式封装&#xff08;包装&#xff09;成一个独立的…

一刷代码随想录——字符串

1 力扣344.反转字符串题目描述&#xff1a;编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。class Solution { public:v…