简介:
本设计是一个基于Qt框架,应用Qt信号槽机制,一个加减乘除的四则混合运算功能的数字型计算器界面的设计与实现,采用Widget类界面,界面包含一个液晶显示窗口(LCD Number);0-9十个数字按钮以及一个小数点‘.’按钮;“+、-、×、÷、=、<-(删除)、CE(清除所输入的一行数字即当时在屏幕上显示的一行数字)、C(全部清零)、+/-”9个运算符号;输入的数字显示在液晶显示窗口,实现整数和小数的四则运算,按下“=”键后将运算结果显示在液晶显示窗口。该计算器是一个集继承、图形界面、事件处理等面向对象编程知识的综合应用的实例程序。
1.系统功能图:
2.界面实现方法:
本计算器采用了QLCDNumber液晶,PushButton按钮控件,QLCDNumber控件它可以显示几乎任意大小的数字,可以显示十进制、十六进制、八进制或二进制数,很容易使用display()槽连接到数据源,当显示范围以外的数据时,就会发射overflow()信号,返回可以通过setDigitCount()来设置。
通过在Qt Creater环境中新建一个Qt Widgets Application应用程序,并新建一个QWidget窗口类,在Qt Creater界面设计器中加入一个QLCDNumber液晶显示控件及5行4列的20个QPushButton按钮控件,每个按钮对象的text属性设置为0-9数字、+-*/运算符、+/-取反、退格、CE、C、小数点和=值,界面效果如下图所示。
3.功能实现方法:
在设计好界面之后选择需要操作的按键右键选择转到槽如图3-2,此处利用了Qt的信号与槽机制,选择clicked()如图3-3,会跳转到程序代码部分,Qt会自动在widget.h文件的private slots添加函数声明,并且在widget.cpp文件等待用户编写事件的函数体。
图3-2
图3-3
加法功能算法即用户点击键盘数字输入第一个运算数存入预置数组中,点击加号会根据标志位判断此前有几个运算数,如果已有两个则先将其进行运算的结果作为第一个运算数再与下一个输入的运算数进行运算,否则继续读取第二个运算数,当用户按下=等于号将第一个运算数与第二个运算数相加的值显示在LCD上。
减法功能算法即用户点击键盘数字输入第一个运算数存入预置数组中,点击减号会根据标志位判断此前有几个运算数,如果已有两个则先将其进行运算的结果作为第一个运算数再与下一个输入的运算数进行运算,否则继续读取第二个运算数,判断减法的减数与被减数返回正值还是负值,当用户按下=等于号将第一个运算数与第二个运算数相减的值显示在LCD上。
乘法功能算法即用户点击键盘数字输入第一个运算数存入预置数组中,点击乘号会根据标志位判断此前有几个运算数,如果已有两个则先将其进行运算的结果作为第一个运算数再与下一个输入的运算数进行运算,否则继续读取第二个运算数,当用户按下=等于号将第一个运算数与第二个运算数相乘的值显示在LCD上。
除法功能算法即用户点击键盘数字输入第一个运算数存入预置数组中,点击减号会根据标志位判断此前有几个运算数,如果已有两个则先将其进行运算的结果作为第一个运算数再与下一个输入的运算数进行运算,否则继续读取第二个运算数,当用户输入的除数为0时会有提示用户除数不可以为0的弹窗提醒,当用户按下=等于号将第一个运算数与第二个运算数相除的值显示在LCD上
实现代码:
widget.h 文件内容:
1 #ifndef WIDGET_H
2 #define WIDGET_H
3 #include <QWidget>
4 #include <string.h>
5 #include <stdio.h>
6 #include <QDialog>
7 #include <QPaintEvent>
8 QT_BEGIN_NAMESPACE
9 namespace Ui {
10 class Widget;
11 }
12 QT_END_NAMESPACE
13 class QErrorMessage;
14 class Widget : public QWidget
15 {
16 Q_OBJECT
17 public:
18 explicit Widget(QWidget *parent = 0);
19 ~Widget();
20 private slots:
21 void to_addn(int i);//添加一个数字函数
22 void to_shown(); //液晶显示函数
23 void two_Operat(); //运算符函数
24 double OpreatorTrues();//运算符判别函数
25 void to_sts(double c);
26 void paintEvent(QPaintEvent *event);
27 void on_pushButton_clicked();//点击+按键
28 void on_pushButton_2_clicked();//点击-按键
29 void on_pushButton_3_clicked();//点击X按键
30 void on_pushButton_4_clicked();//点击÷按键
31 void on_pushButton_5_clicked();//点击7按键
32 void on_pushButton_6_clicked();//点击8按键
33 void on_pushButton_7_clicked();//点击9按键
34 void on_pushButton_8_clicked();//点击CE按键
35 void on_pushButton_9_clicked();//点击4按键
36 void on_pushButton_10_clicked();//点击5按键
37 void on_pushButton_11_clicked();//点击6按键
38 void on_pushButton_12_clicked();//点击C按键
39 void on_pushButton_13_clicked();//点击1按键
40 void on_pushButton_14_clicked();//点击2按键
41 void on_pushButton_15_clicked();//点击3按键
42 void on_pushButton_16_clicked();//点击<-按键
43 void on_pushButton_17_clicked();//点击+/-按键
44 void on_pushButton_18_clicked();//点击0按键
45 void on_pushButton_19_clicked();//点击.按键
46 void on_pushButton_20_clicked();//点击=按键
47 private:
48 Ui::Widget *ui;
49 QErrorMessage * errortip;//提示语句
50 double one = 0, two = 0;//定义运算数变量
int oper, a = 0, b = 10, lens=0;
51 char conceq[100];//定义存储数据数组
52 bool sign = false, signdian = false, starta = false, startb = false, signa = true, signb = true;
53 };
54 #endif // WIDGET_H
widget.cpp 文件内容:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include<string>
#include<QString>
#include<QErrorMessage>
#include<QPainter>
#include <QPaintEvent>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
errortip = new QErrorMessage(this); //创建提示语句对象
ui->lcdNumber->setDigitCount(8); //设置lcd液晶显示位数为八位
}
constexpr double num = 0.0000000001;
Widget::~Widget()
{
delete ui;
}
void Widget::paintEvent(QPaintEvent *event)//主窗口显示背景图片(主窗口使用的QWidget类,重构paintEvent事件)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
void Widget::to_addn(int i) //当点击数字按钮调用本函数将数字添加
{
conceq[lens++] = char(48+i);//存入数字数字串长度增加1
conceq[lens] = '\0'; //在数字串结尾添加结束符号
if((signdian && lens == 10) || (!signdian && lens == 9)){//当数字串长度超过8会输出错误提示
errortip->setWindowTitle(tr("输入错误提示")); //输入数据超出提示语句标题
errortip->showMessage(tr("输入数据超出限制")); //输入数据超出提示内容
conceq[--lens] = '\0'; //数字串长度减一,在数字串结尾添加结束符号
return;
}
a= i;//将输入数字值赋给全局变量a
if(!sign){//当sign标志为假
if(!starta){//当starta标志为假即未输入第一个运算数
conceq[0] = char(48+i);//将输入数字存入数组第0位
conceq[1] = '\0';//数组第1位为结束符
lens = 1;//数组长度为1
starta = true;//将starta标志为真存储第一个运算数
}
if(signdian){//当小数点存在
one = one + double(i) /b;//one中存储整数部分加上小数部分
b *= 10;//b累乘10即下一个输入的数字向小数点后移
}else{//当小数点不存在
one = one * 10 + i;//one中存储one的值*10后加上新输入的数字
}
}else{//当sign标志为真
if(!startb){//当startb标志为假即未输入第二个运算数
conceq[0] = char(48+i);//将输入数字存入数组第0位
conceq[1] = '\0';//数组第1位为结束符
lens = 1;//数组长度为1
startb = true;//将startb标志为真存储第二个运算数
}
if(signdian){//当小数点存在
two = two + double(i) / two;//two中存储整数部分加上小数部分
b *= 10;//b累乘10即下一个输入的数字向小数点后移
}else{
two = two * 10 + i;//two中存储two的值*10后加上新输入的数字
}
}
to_shown();//调用显示函数将数字显示在液晶lcd上
}
void Widget::to_shown()//显示函数将conceq数组内容显示在液晶lcd上
{
qDebug() << conceq;//输出数组存储的内容
if(lens == 0){
ui->lcdNumber->display(0);
}else{
ui->lcdNumber->display(conceq);
}
}
void Widget::two_Operat()
{
two = 0;//变量two的值清零
signb = true;//将signb标志为真
signa = true;//将signa标志为真
starta = true;//将starta标志为真
startb = false;//将startb标志为假
b = 10;//变量b的值归10
lens=0;//数组长度为0
conceq[0] = '\0';
signdian = false;//小数点置为假
}
double Widget::OpreatorTrues()
{
switch (oper) {
case 1 : return one + two;//加法运算返回one+two的值
case 2 : return one - two;//减法运算返回one-two的值
case 3 : return one * two;//乘法运算返回onextwo的值
case 4 : {
if(two>=-num && two<=num){
errortip->setWindowTitle(tr("错误提示"));
errortip->showMessage(tr("除数不能为0"));
return one;
} return one / two;//除法运算返回one/two的值
}
}
return a;
}
void Widget::to_sts(double c)
{
sprintf(conceq, "%.8lf", c);
conceq[8] = '\0';//将数组第7位置为结束符
lens = 8;//长度置为8
for(int i=lens-1; i>0; i--){
if(conceq[i] == '0'){//若数组第i位置为0
conceq[i] = '\0';//将数组第i位置为结束符
lens--;//数组长度自减
}else if(conceq[i] == '.'){//若数组第i位置为小数点
conceq[i] = '\0';//将数组第i位置为结束符
lens--;//数组长度自减
break;
}else{
break;
}
}
}
void Widget::on_pushButton_clicked()
{//+
qDebug()<<"+";//输出+号
if(sign){//当sign标志为真即已有俩运算数
if(!signa) one = 0 - one;//当signa标志为假one取反
if(!signb) two = 0 - two;//当signb标志为假two取反
one = OpreatorTrues();
two_Operat();
oper = 1;
to_sts(one);
to_shown();
}else{//当sign标志为假即只有一个运算数
if(!signa) one = 0 - one;//当signa标志为假one取反
oper = 1;
sign = true;//将sign标志为真即已有俩运算数
two_Operat();
}
}
void Widget::on_pushButton_2_clicked()
{//-
qDebug()<<"-";
if(sign){
if(!startb){
startb = true;//将startb标志为真
signb = false;//将signb标志为假
conceq[0] = '-';//数组第0位为-号
conceq[++lens] = '\0';//数组第长度加一位为结束符
to_shown();
}else{
if(!signa) one = 0 - one;//当signa标志为假one取反
if(!signb) two = 0 - two;//当signb标志为假two取反
one = OpreatorTrues();
two_Operat();
oper = 2;//选择2减法
to_sts(one);
to_shown();
}
}else{
if(!starta){
starta = true;//将starta标志为真
signa = false;//将signa标志为假
conceq[0] = '-';//数组第0位为-号
conceq[++lens] = '\0';//数组第长度加一位为结束符
to_shown();
}else{
if(!signa) one = 0 - one;//当signa标志为假one取反
oper = 2;//选择2减法
two_Operat();
sign = true;
}
}
}
void Widget::on_pushButton_3_clicked()
{//cheng
qDebug()<<"*";
if(sign){
if(!signa) one = 0 - one;//当signa标志为假one取反
if(!signb) two = 0 - two;//当signb标志为假two取反
one = OpreatorTrues();
two_Operat();
oper = 3;//选择3乘法
to_sts(one);
to_shown();//结果显示函数
}else{
if(!signa) one = 0 - one;//当signa标志为假one取反
oper = 3;//选择3乘法
two_Operat();
sign = true;
}
}
void Widget::on_pushButton_4_clicked()
{//chu
qDebug()<<"÷";
if(sign){
if(!signa) one = 0 - one;//当signa标志为假one取反
if(!signb) two = 0 - two;//当signb标志为假two取反
one = OpreatorTrues();
two_Operat();
oper = 4;//选择4除法
to_sts(one);
to_shown();//结果显示函数
}else{
if(!signa) one = 0 - one;//当signa标志为假one取反
oper = 4;//选择4除法
two_Operat();
sign = true;
}
}
void Widget::on_pushButton_5_clicked()
{//7
to_addn(7);//按下数字7调用to_add函数将7添加
}
void Widget::on_pushButton_6_clicked()
{//8
to_addn(8);//按下数字8调用to_add函数将8添加
}
void Widget::on_pushButton_7_clicked()
{//9
to_addn(9);//按下数字9调用to_add函数将9添加
}
void Widget::on_pushButton_8_clicked()
{//ce
if(sign){
two_Operat();
two = 0;
b = 10;
signdian = false;//小数点置为假
startb = false;
to_sts(two);
to_shown();//结果显示函数
}else{
one = 0;
b = 10;
signdian = false;//小数点置为假
starta = false;
to_sts(one);
to_shown();//结果显示函数
}
}
void Widget::on_pushButton_9_clicked()
{//4
to_addn(4);//按下数字4调用to_add函数将4添加
}
void Widget::on_pushButton_10_clicked()
{//5
to_addn(5);//按下数字5调用to_add函数将5添加
}
void Widget::on_pushButton_11_clicked()
{//6
to_addn(6);//按下数字6调用to_add函数将6添加
}
void Widget::on_pushButton_12_clicked()//将各个变量及标志回归初始值
{//c
one = 0; two = 0;
a = 0; b = 10; lens=0; oper=0;
conceq[0] = '\0';
sign = false; signdian = false; starta = false;
startb = false; signa = true; signb = true;
to_sts(0.0);
to_shown();
}
void Widget::on_pushButton_13_clicked()
{//1
to_addn(1);//按下数字1调用to_add函数将1添加
}
void Widget::on_pushButton_14_clicked()
{//2
to_addn(2);//按下数字2调用to_add函数将2添加
}
void Widget::on_pushButton_15_clicked()
{//3
to_addn(3);//按下数字3调用to_add函数将3添加
}
void Widget::on_pushButton_16_clicked()
{//<-
if(!sign){
if(signdian){
one = one * b / 10;
one -= a;
one /= b;
b /= 10;
if(b == 1){
signdian = false;
b = 10;
}
}else{
one -= a;
one /= 10;
a = int(one) % 10;
}
}else{
if(signdian){
two = two * b;
two -= a;
a = (int(two) % 100) / 10;
two /= b;
b /= 10;
if(b == 1){
signdian = false;
b = 10;
}
}else{
two -= a;
two /= 10;
a = int(two) % 10;
}
}
if(lens>0){
conceq[--lens] = '\0';//数据长度自减
}
to_shown();//结果显示函数
}
void Widget::on_pushButton_17_clicked()
{//+-
if(sign){
if(startb){
if(signb){
signb = false;
for(int i=(++lens); i>0; i--){//原来存储的数据向后移动一位
conceq[i] = conceq[i-1];
}
conceq[0] = '-';//数据第0位为-号
to_shown();//结果显示函数
}else{
signb = true;
for(int i=0; i<lens; i++){
conceq[i] = conceq[i+1];//原来存储的数据向前移动一位
}
lens--;//数据长度自减
to_shown();//结果显示函数
}
}else{
startb = true;
signb = false;
conceq[0] = '-';//数据第0位为-号
conceq[++lens] = '\0';//结束符后移一位
to_shown();//结果显示函数
}
}else{
if(starta){
if(signa){
signa = false;
for(int i=(++lens); i>0; i--){//原来存储的数据向后移动一位
conceq[i] = conceq[i-1];
}
conceq[0] = '-';//数据第0位为-号
to_shown();//结果显示函数
}else{
signa = true;
for(int i=0; i<lens; i++){
conceq[i] = conceq[i+1];//原来存储的数据向前移动一位
}
lens--;//数据长度自减
to_shown();//结果显示函数
}
}else{
starta = true;
signa = false;
conceq[0] = '-';//数据第0位为-号
conceq[++lens] = '\0';//结束符后移一位
to_shown();//结果显示函数
}
}
}
void Widget::on_pushButton_18_clicked()
{//0
to_addn(0);//按下数字0调用to_add函数将0添加
}
void Widget::on_pushButton_19_clicked()
{//.
if(!signdian){
signdian = true;//将小数点标志位为真
conceq[lens++] = '.';//将小数点存入conceq数组
conceq[lens] = '\0';//小数点增加后结束符后移
to_shown();
}
}
void Widget::on_pushButton_20_clicked()
{//=
qDebug()<<"=";
if(sign){
sign = false; //将标志位置为假
if(!signa) one = 0 - one; //当第一个运算数为负数则将其取反
if(!signb) two = 0 - two; //当第二个运算数为负数则将其取反
one = OpreatorTrues();
two_Operat();
to_sts(one);
to_shown();
}else{
if(!signa) one = 0 - one;
two_Operat();
sign = true; //将标志位置为真
}
}
main.cpp 文件内容:
1 #include "widget.h"
2 #include <QApplication>
3 int main(int argc, char *argv[])
4 {
5 QApplication a(argc, argv);
6 Widget w;
7 w.show();
8 return a.exec();
9 }