Back-end separation calculator programming

The Link Your Classhttp://t.csdnimg.cn/xdDRg
The Link of Requirement of This Assignmenthttps://bbs.csdn.net/topics/617378696
The Aim of This AssignmentBack-end separation calculator programming
MU STU ID and FZU STU ID21124671_832101213

Link to the finished project code and coding standard(codestyle): code address

I. PSP form

Personal Software Process StagesEstimated Time(minutes)Actual Time(minutes)
Planning
• Estimate3040
Development
• Analysis3030
• Design Spec3030
• Design Review1010
• Coding Standard2030
• Design4030
• Coding360420
• Code Review6090
• Test3030
Reporting
• Test Report6060
• Size Measurement1010
• Postmortem & Process Improvement Plan1010
Sum690790

II. Problem-solving ideas

In order to implement the calculator, I firstly searched for a variety of methods on Internet. After a simple search, I chose to use qt to complete the calculator. For convenience, I chose to use visual studio to assist.
QT is very easy and convenient to construct a visual interface. Then it is possible to write the logic of the individual buttons through visual studio.
I can have a basic understanding of QT through the project. I learnt how to construct the basic visual interface as well.

III. Design and implementation process

1. Front-end

I use QT designer to design the surface. I create 2 windows, which are the calculator and history. Style sheet is used to make the interface more beautiful.
In the calculator, perform different functions according to different click events. For example, digits and dot are different from operators. There are also other function buttons.
Qvector is used to access expressions and results during operations and perform different functions depending on eace case of bit of the Qvector.

2. Back-end

I used to use mysql to connect the database directly but failed many times. So to be replaced I use ODBC to connect the database.
The table is manipulated bt executing sql statements.
Next is the process.
When calculator is open, clear the table “history” in the database “calculator”.
When users push “=”, expression is sented to the table “history” in the database"calculator".
When users push “ANS”, read the latest field in the table and display it in the lineEdit.
When users push “history”, the window of history is shown and showEvent is triggered. In the showEvent, database is connected and the latest 10 fields of the table are read in turn and then displayed in the lineEdits in the window one by one.

3. Flowchart

calculator to database

IV. Code Explanation

1. Front-end

在这里插入图片描述
在这里插入图片描述
basic interface of calculator

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>calculatorClass</class>
 <widget class="QWidget" name="calculatorClass">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>300</width>
    <height>400</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>300</width>
    <height>400</height>
   </size>
  </property>
  <property name="maximumSize">
   <size>
    <width>400</width>
    <height>500</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>calculator</string>
  </property>
  <property name="styleSheet">
   <string notr="true">*
{
 border:none;
 background-color:rgb(238, 236, 236);
}

Push button of calculator

QPushButton
{
 background-color:rgb(243, 243, 243);
}

QPushButton:hover
{
 border:1px solid rgb(193, 193, 193);
 background-color:rgb(220, 220, 220);
}

QPushButton#btn_0,#btn_1,#btn_2,#btn_3,#btn_4,#btn_5,#btn_6,#btn_7,#btn_8,#btn_9
{
 font:bold 12pt'微软雅黑';
 background-color:rgb(252, 252, 252);
}

QPushButton#btn_0:hover,#btn_1:hover,#btn_2:hover,#btn_3:hover,#btn_4:hover,#btn_5:hover,#btn_6:hover,#btn_7:hover,#btn_8:hover,#btn_9:hover
{
 border:1px solid rgb(193, 193, 193);
 background-color:rgb(220, 220, 220);
}

basic interface of history

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>HistoryClass</class>
 <widget class="QWidget" name="HistoryClass">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>200</width>
    <height>400</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>200</width>
    <height>400</height>
   </size>
  </property>
  <property name="maximumSize">
   <size>
    <width>200</width>
    <height>400</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>History</string>
  </property>
  <property name="styleSheet">
   <string notr="true">*
{
 border:none;
 background-color:rgb(238, 236, 236);
}

lineEdit of history

QLineEdit
{
 background-color:rgb(252, 252, 252);
}

String of calculator and history is too long so it won’t be put here

Main program
calculator
Head file

#pragma once

#include <QtWidgets/QWidget>
#include "ui_calculator.h"
#include "History.h"

QT_BEGIN_NAMESPACE
namespace Ui { class calculatorClass; };
QT_END_NAMESPACE

class calculator : public QWidget
{
    Q_OBJECT

public:
    calculator(QWidget *parent = nullptr);
    ~calculator();
    void iniUI();
    bool isInteger(double n);
    void lineEditClear();//clear the lineEdit and lineEdit_exp, initial
    History ht;
public slots:
    void onButtonGroupClicked(QAbstractButton* btn);
    void showHistory();//show the window of history
private:
    Ui::calculatorClass *ui;
    QVector<QVariant> vec;//save the expressions and results
    QString prevBtn;//save the previous button
    bool start;//judge if start of a expression
};

library

#include "calculator.h"
#include "database.h"
#include <qbuttongroup.h>
#include <qdebug.h>
#include <qvector.h>
#include <iomanip>
#include <iostream>
#include <math.h>

calculator

calculator::calculator(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::calculatorClass())
{
    ui->setupUi(this);
    iniUI();
    if (!createConnection()) qInfo() <<"fail"; //create connection to the database
    else qInfo() << "success";

    connect(ui->pushButton_history, SIGNAL(clicked()), this, SLOT(showHistory()));//connect the window of history the the pushBotton of history
}

iniUI

void calculator::iniUI()
{
    auto buttonGroup = new QButtonGroup(this);//to save buttons
    auto btnlist = findChildren<QPushButton*>();

    QSqlDatabase db2 = QSqlDatabase::database("connection1"); //connect the database
    QSqlQuery query2(db2);

    for (auto btn : btnlist)
    {
        buttonGroup->addButton(btn);
    }//find all buttons
    
    connect(buttonGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked), this, &calculator::onButtonGroupClicked);
    vec.resize(5);
    query2.exec("delete from history");//initial the table history
}

showHistory

void calculator::showHistory()//show the window of history
{
    ht.show();
}

detect integer

bool calculator::isInteger(double n)
{
    if (n - int(n) == 0)
    {
        return true;
    }
    else return false;
}

clear all

void calculator::lineEditClear()//clear the lineEdit and lineEdit_exp, initial
{
    ui->lineEdit->clear();
    ui->lineEdit->insert("0");
    ui->lineEdit_exp->clear();
    vec.clear();
    vec.resize(5);
}

click events
void calculator::onButtonGroupClicked(QAbstractButton* btn)
start

QString expression;
    bool equal = false; //if push the "=", equal is true
    qreal val = ui->lineEdit->text().toDouble();
    qInfo() << btn->text(); 
    QString name = btn->text();

    QSqlDatabase db2 = QSqlDatabase::database("connection1"); //connect the database
    QSqlQuery query2(db2);

if push digits or dot

if (name>="0" && name<="9" ||name ==".")
    {
        if (start&&vec[1].isNull()) //if user push the digit, cover the previous result, if push the operator, the previous result is regarded as x in the expression
        {
            lineEditClear();
            start = false;
        }
        if (name != "."&& ui->lineEdit->text()=="0")  ui->lineEdit->clear();
        

        if (prevBtn == "+"|| prevBtn == "-" || prevBtn == "*" || prevBtn == "/" || prevBtn == "%")
        {
            ui->lineEdit->clear();
        }
        if (name == "." && !isInteger(val));
        else ui->lineEdit->insert(name);
    }//for digit or dot

if push operators

else if (name == "+")
    {
        if (vec[2].isNull())
        {
            vec[0] = val;
            vec[1] = "+";
        }
    }
    else if (name == "-")
    {
        if (vec[2].isNull())
        {
            vec[0] = val;
            vec[1] = "-";
        }
    }
    else if (name == "*")
    {
        if (vec[2].isNull())
        {
            vec[0] = val;
            vec[1] = "*";
        }
    }
    else if (name == "/")
    {
        if (vec[2].isNull())
        {
            vec[0] = val;
            vec[1] = "/";
        }
    }
    else if (name == "%")
    {
        if (vec[2].isNull())
        {
            vec[0] = val;
            vec[1] = "%";
        }
    }
    //for operators

if push “=” to end the expression

else if (name == "=")
    {
        start = true;
        equal = true;
        vec[2] = val;
        vec[3] = "=";
        expression = vec[0].toString() + vec[1].toString() + vec[2].toString() + "=";
        if (vec[1] == "+")
        {
            vec[4] = vec[0].toDouble() + vec[2].toDouble();
        }
        if (vec[1] == "-")
        {
            vec[4] = vec[0].toDouble() - vec[2].toDouble();
        }
        if (vec[1] == "*")
        {
            vec[4] = vec[0].toDouble() * vec[2].toDouble();
        }
        if (vec[1] == "/")
        {
            vec[4] = vec[0].toDouble() / vec[2].toDouble();
        }
        if (vec[1] == "%")
        {
            vec[4] = vec[0].toInt() % vec[2].toInt();
        }
        vec[4] = round(vec[4].toDouble()*100)/100;
        ui->lineEdit->setText(vec[4].toString());

        //insert the expression into the table
        query2.clear();
        query2.prepare("insert into history (x, operator, y, result) values (?, ?, ?, ?)");
        query2.addBindValue(vec[0]);
        query2.addBindValue(vec[1]);
        query2.addBindValue(vec[2]);
        query2.addBindValue(vec[4]);
        query2.exec();
        

        QVariant temp = vec[4];
        vec.clear();
        vec.resize(5);
        vec[0] = temp;
    }

clear, clear enter, delete

//clear
    else if (name=="C")
    {
        lineEditClear();
    }
    //clear error
    else if (name == "CE")
    {
        ui->lineEdit->clear();
        ui->lineEdit->insert("0");
    }
    //delete
    else if (name == "Del")
    {
        if (vec[1].isNull())
        {
            ui->lineEdit->setCursorPosition(ui->lineEdit->cursorPosition() - 1);
            ui->lineEdit->del();
        }
        else vec[1] = NULL;
    }

1/x and +/-

//upside down
    else if (name == "+/-")
    {
        QString temp = ui->lineEdit->text();
        if (val >= 0) ui->lineEdit->setText("-" + temp);
        else  ui->lineEdit->setText(temp.mid(1, temp.length() - 1));
    }
    else if (name == "l/x")
    {
        QVariant val_ = 1 / val;
        ui->lineEdit->setText(val_.toString());
    }

if push “ANS”

else if (name == "ANS")
    {
        QSqlQuery expressions = db2.exec(" select * from history");//all field in the history
        if (expressions.last())//the last field
        {
            //ui->lineEdit_exp->setText(expressions.value("x").toString()+ expressions.value("operator").toString()+ expressions.value("y").toString()+"=");
            ui->lineEdit->setText(expressions.value("result").toString());
        }
    }

end

ui->lineEdit_exp->clear();

    if (!equal)//lineEdit_exp display the current expression which is incomplete
    {
        for (auto var : vec) ui->lineEdit_exp->insert(var.toString());
    }
    else //lineEdit_exp display the expression of the current result
    {
        ui->lineEdit_exp->setText(expression);
        equal = false;
    }
    
    prevBtn = name;

2. Back-end

head file of database

#include <QSqlDatabase>	
#include <QSqlError>		
#include <QSqlQuery>		
#include <QMessageBox>
#include <QVariantList>			
#include <QDebug>
#include <QString>


static bool createConnection() {
	QSqlDatabase db = QSqlDatabase::addDatabase("QODBC","connection1");
	db.setHostName("127.0.0.1");
	db.setPort(3306);
	db.setDatabaseName("calculator"); //data source name in ODBC, which is the same as the database name
	db.setUserName("root");
	db.setPassword("968574123Sjz"); //password

	// open the database
	if (!db.open()) {	// if fail
		return false;
	}
	else {
		return true;
	}
}

head file of the history window

#pragma once

#include <QWidget>
#include "ui_History.h"

class History : public QWidget
{
	Q_OBJECT

public:
	History(QWidget *parent = nullptr);
	~History();

private:
	Ui::HistoryClass ui;
protected:
	virtual void showEvent(QShowEvent* event) override;//execute when the window of history is displayed
};

main program of history window
History

History::History(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

    if (!createConnection()) qInfo() << "fail"; //create connection to the database
    else qInfo() << "success";
    
}

showEvent

void History::showEvent(QShowEvent* event)
{
    QSqlDatabase db2 = QSqlDatabase::database("connection1"); //connect the database
    QSqlQuery query2(db2);

    QVector<QLineEdit*> lineEdits;
    lineEdits.resize(11);
    lineEdits = { ui.lineEdit_1, ui.lineEdit_2, ui.lineEdit_3, ui.lineEdit_4, ui.lineEdit_5, ui.lineEdit_6, ui.lineEdit_7, ui.lineEdit_8, ui.lineEdit_9, ui.lineEdit_10 };//store lineEdits for traversal
    int i = 0;

    //display past 10 or less expressions in the lineEdits of window
    QSqlQuery expressions = db2.exec(" select * from history");
    if (expressions.last())
        ui.lineEdit_1->setText(expressions.value("x").toString() + expressions.value("operator").toString() + expressions.value("y").toString() + " = " + expressions.value("result").toString());
    while (expressions.previous() && ++i < 10) //the last 10 fields
        lineEdits[i]->setText(expressions.value("x").toString() + expressions.value("operator").toString() + expressions.value("y").toString() + " = " + expressions.value("result").toString());
}

V. Presentation

zoom in and out of the application
请添加图片描述

basic function(add, substract, multiply, divide and remainder)
请添加图片描述
1/x
请添加图片描述
+/-(upside down)请添加图片描述

CE(clear enter) and C(clear)
请添加图片描述
delete
请添加图片描述
ANS
请添加图片描述
History
请添加图片描述

VI. Personal Journey and Learnings

The calculator remains to be perfected. The calculator can work with only 2 numbers and complex calculations with multiple numbers are impossible.
There is some coupling between the front-end and the back-end.
It connects the local database not the cloud server.
Through the project, I have a preliminary understanding of the project process. I learn how to build a simple visual interface by qt, code with visual studio and connect both of them.
I learn how to connect database by ODBC and how to manipulate tables in the database by sql statements.
I have a relatively simple understanding of the front-end and back-end.

VII. Reference

https://blog.csdn.net/cpp_learner/article/details/109769505
https://blog.csdn.net/joey_ro/article/details/105411135

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值