基于QT(c++)的家庭财务管理系统
程序员文章站
2022-04-28 09:02:25
...
题目:家庭财务管理系统
前言:
家庭财务管理收支管理是一个家庭日常生活中不可缺少一部分,也是财务管理的重要组成部分。
题目要求:
开发一个家庭财务管理系统,实现家庭财务信息的自动化。
系统主要功能:
1.登陆管理 :可以选一名家庭成员做管理员,普通用户只能查看自己的收支信息。
2. 家庭成员管理:成员的信息:姓名、性别、出身日期、年龄,身高,体重。
3. 收支项目管理可以设置收支项目,修改或者删除。收支项目要求分为两层,比如“车辆维护-保养费”;任意一层次都可作为收支项目记账,用户在不清楚支出是否属于“保养费”的时候,可以选择大类“车辆维护”作为支出项
5.家庭成员收支输出 显示每个成员每月的收支情况(时间、收支种类、金额、经手人)。
6.退出管理
下面是系统功能示意图:
系统的设计思路如下:
功能实现一:登录窗口实现
ui界面如下:
1.管理员登录
- 管理员登录功能实现:在登录窗口类loginDlg定义私有成员:管理员账号与管理员密码,通过
#include<QSettings> //Qt提供用于写入注册表的类
读写注册表。
- 通过lineEdit行编辑输入用户名密码,在代码段中通过管理员登陆的Radio Button是否选中进行判断是否进行管理员登录。
2.管理员密码修改
- 通过点击左下角的管理员密码修改按钮进行密码修改(进入密码修改对话框),对话框界面如下:
密码修改对话框具体功能实现在此先不做具体介绍,
注意:此处密码修改需要用到加密算法,这里使用QT提供用于密码加密的类:
#include<QCryptographicHash> //Qt提供用于加密的类
3.普通用户登录:读取数据库
- 基于QSqlite轻量级数据库,未选中管理员登录Radio Button时,默认为普通用户登录。
以下为具体代码:
logindlg.h
#ifndef LOGINDLG_H
#define LOGINDLG_H
#include <QDialog>
#include<QSettings>
#include<QByteArray>
#include<QCryptographicHash> //Qt提供用于加密的类
#include<QMessageBox>
#include <QTextCodec> //unicode编码与其他编码转换
#include <QSqlDatabase> //提供通过连接访问数据库的接口
#include <QSqlQuery> //sql查询中创建、导航和检索数据所涉及的功能
#include <QTime>
#include <QSqlError>
#include <QDebug>
#include <QSqlDriver>
#include <QSqlRecord>
#include <QLabel>
#include <QDataWidgetMapper>
#include <QTemporaryFile>
#include <QFile>
#include <QByteArray>
#define SUB -1
#define MAIN 1
namespace Ui {
class loginDlg;
}
class loginDlg : public QDialog
{
Q_OBJECT
public:
explicit loginDlg(QWidget *parent = nullptr);
~loginDlg();
void setName(QString name) {Mng_Name = name;}
void setPswd(QString pswd) {Mng_Pswd = pswd;}
bool createConnection(); //创建数据库链接
bool queryAll(QString name, QString pswd); //查找数据库
void SetTabOrder(); //设置tab切换顺序
int SubOrMain; //主,从窗口切换标志
QString NormalUser; //普通用户账号
private:
Ui::loginDlg *ui;
void readSettings(); //读取设置,注册表
void writeSettings(); //写入设置,注册表
int Mng_tryCount = 0; //试错次数
QString encrypt(const QString& str); //字符串加密
QString Mng_Name = "user"; //初始化用户名
QString Mng_Pswd = "123456"; //初始化密码
QSqlDatabase DB;
private slots:
void on_LoginPushButton_clicked();
void on_SignOutPushButton_clicked();
void ChangePwd(); //修改密码
void on_radioButton_clicked();
};
#endif // LOGINDLG_H
logindlg.cpp
#include "logindlg.h"
#include "ui_logindlg.h"
loginDlg::loginDlg(QWidget *parent) :
QDialog(parent),
ui(new Ui::loginDlg)
{
ui->setupUi(this);
this->setWindowTitle("登陆窗口");
this->setAttribute(Qt::WA_DeleteOnClose);
// Mng_Pswd = encrypt("123456");
// writeSettings();
SetTabOrder();
readSettings(); //初始化注册管理员用户名和密码
createConnection();
connect(ui->ChangePswd_PB, SIGNAL(clicked()), this, SLOT(ChangePwd()));
}
loginDlg::~loginDlg()
{
delete ui;
}
bool loginDlg::createConnection()
{
DB = QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动
DB.setDatabaseName("../familyDb.db");
if (!DB.open()) //打开数据库
{
QMessageBox::warning(this, "错误", "打开数据库失败",
QMessageBox::Ok,QMessageBox::NoButton);
return false;
}
return true;
}
bool loginDlg::queryAll(QString name, QString pswd)
{
DB = QSqlDatabase::database(); //使用默认连接
QSqlQuery query(DB);
query.exec("select * from familyBase");
while(query.next())
{
if(query.value(6).toString()==name&&query.value(7).toString()==pswd)
return true;
}
return false;
}
void loginDlg::SetTabOrder()
{
setTabOrder(ui->IDLineEdit, ui->PassWordLineEdit);
setTabOrder(ui->PassWordLineEdit, ui->LoginPushButton);
setTabOrder(ui->LoginPushButton, ui->SignOutPushButton);
setTabOrder(ui->SignOutPushButton, ui->radioButton);
setTabOrder(ui->radioButton, ui->ChangePswd_PB);
setTabOrder(ui->ChangePswd_PB, ui->radioButton);
}
void loginDlg::readSettings()
{//读取存储的用户名和密码, 密码是经过加密的
QString organization = "TJJ-Qt"; //用于注册表
QString appName = "FIO_System"; //app名字
QSettings settings(organization, appName);
Mng_Name = settings.value("Username","user").toString();
QString defaultPSWD = encrypt("123456"); //缺省密码“123456”加密后的数据
Mng_Pswd = settings.value("PSWD", defaultPSWD).toString(); //读取PSWD
}
void loginDlg::writeSettings()
{//保存用户名,密码等设置
QSettings settings("TJJ-Qt", "FIO_System"); //注册表键组
settings.setValue("Username",Mng_Name); //将管理员账号存至设置
settings.setValue("PSWD",Mng_Pswd); //将管理员密码存至设置
//指向的注册表目录是HKEY_CURRENT_USER/Software/TJJ-Qt/家庭收支管理系统
}
QString loginDlg::encrypt(const QString &str)
{ //字符串MD5算法加密
QByteArray btArray;
btArray.append(str);//加入原始字符串
QCryptographicHash hash(QCryptographicHash::Md5); //Md5加密算法
hash.addData(btArray); //添加数据到加密哈希值
QByteArray resultArray =hash.result(); //返回最终的哈希值
QString md5 =resultArray.toHex();//转换为16进制字符串
return md5;
}
void loginDlg::on_LoginPushButton_clicked()
{
QString user = ui->IDLineEdit->text().trimmed(); //输入用户名
QString pswd = ui->PassWordLineEdit->text().trimmed(); //输入密码
QString encrptPSWD = encrypt(pswd); //对输入密码进行加密
if(ui->radioButton->isChecked())
{
if ((user == Mng_Name)&&(encrptPSWD == Mng_Pswd)) //如果用户名和密码正确
{
writeSettings(); //保存设置
SubOrMain = MAIN;
this->accept(); //对话框accept(),关闭对话框
}
else
{
Mng_tryCount++; //错误次数
if (Mng_tryCount>3)
{
QMessageBox::critical(this, "提示", "已达最大试错次数,程序退出");
exit(1);
}
else
{
QMessageBox::warning(this, "错误提示", "用户名或密码错误");
return;
}
}
}
else
{
if(queryAll(user,pswd))
{
NormalUser = user;
QFile file("../UserNameFile.txt");
// if (file.open(QIODevice::ReadWrite | QIODevice::Text))
// {
// file.write(NormalUser.toLatin1());
// file.flush();
// file.close();
// }
// QFile file("要写的文件路径");
if (file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream stream(&file);
stream.seek(file.size());
QString qs;
for (auto& i : user)
{
qs.append(i);
}
stream << qs;
file.close();
SubOrMain = SUB;
this->accept(); //对话框accept(),关闭对话框
}
}
//QFile::setPermissions("UserNameFile.txt", QFileDevice::ReadUser);
else
{
Mng_tryCount++; //错误次数
if (Mng_tryCount>3)
{
QMessageBox::critical(this, "提示", "已达最大试错次数,程序退出");
exit(1);
}
else
{
QMessageBox::warning(this, "错误提示", "用户名或密码错误");
return;
}
}
}
}
void loginDlg::on_SignOutPushButton_clicked()
{
if(QMessageBox::question(this, "提示", "确定退出程序吗")==QMessageBox::Yes)
{
this->reject(); //退出
}
else
return;
}
void loginDlg::ChangePwd()
{ //修改密码
QSqlQuery query(DB);
ChangePassword *dialog = new ChangePassword(this,"", &Mng_Pswd);
if(dialog->exec() == QDialog::Accepted)
{
Mng_Pswd = encrypt(*dialog->GetNewPswd_Mng());
QMessageBox::information(this, "提示", "密码修改成功" , QMessageBox::Ok);
}
}
void loginDlg::on_radioButton_clicked()
{
ui->IDLineEdit->setFocus();
}
二、管理员窗口实现
一:综述:此界面利用tabWidget实现,三个管理标签页采用同样的实现方式,即采用View和model的形式,设置手动提交操作(利用下方四个按钮实现)。第四页界面如下:
第四页功能设计思路:
- 使用TreeWidget实现月份与姓名的分类,通过点击TreeWidget中的Item实现右边收入项目与支出项目的TableView显示。
- 以下采用不可编辑的lineEdit显示计算出来的月总收入与月总支出。
主要代码如下:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
#include <QSqlTableModel>
#include <QtSql>
#include <QDataWidgetMapper>
#include <QSqlRecord>
#include <QSqlError>
#include <QSqlQuery>
#include <QDateTime>
#include <QDate>
#include <QDebug>
#include <QTreeWidgetItem>
#include <QMessageBox>
#include "infoentry.h"
#include "changepassword.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QSqlDatabase DB;//数据库连接
QSqlTableModel *FamilyBaseTabModel; //数据模型
QSqlTableModel *InItemTabModel; //数据模型
QSqlTableModel *OutItemTabModel; //数据模型
QSqlTableModel *PrintInModel; //收入项目数据模型
QSqlTableModel *PrintOutModel; //支出项目数据模型
QItemSelectionModel *theSelection; //选择模型
QDataWidgetMapper *dataMapper; //数据映射
void DBconnectAndCreateTable(); //连接数据库以及创建表
void openTable(); //打开数据表
void InitFamilyBaseView(); //初始化家庭成员基本信息视图
void InitInItemView(); //初始化收入项目视图
void InitOutItemView(); //初始化输出项目视图
void InitPrintAllTab(); //初始化打印家庭成员信息标签页
QString encrypt(const QString& str); //字符串加密
InfoEntry *InfoEntryDialog; //信息输入窗口指针
private slots:
void SignOut(); //重新登陆
void on_ActionEntry_triggered(); //对信息输入action反应
void TreeWidgetsItemChanged(QTreeWidgetItem*, int); //切换TreeWidget槽函数
void ShowCopyRight(); //版权:谭俊杰
void on_CertainDLTMem_PB_clicked();
void on_CertainDLTIncome_PB_clicked();
void on_AddMember_PB_clicked();
void on_AddInItems_PB_clicked();
void on_OUT_CertainButton_clicked();
void on_OUT_CancelButton_clicked();
void on_Out_AddButton_clicked();
void on_CancelDLTMem_PB_clicked();
void on_ConcelDLTIn_PB_clicked();
void on_DeleteMember_PB_clicked();
void on_DLTInItems_PB_clicked();
void on_Out_DeleteButton_clicked();
// void on_pushButton_7_clicked(); //无效
// void on_IN_CertainButton_clicked(); //无效
// void on_pushButton_5_clicked(); //无效
void on_pushButton_clicked(); //查找月份
};
#endif // MAINWINDOW_H
mainwindow.cpp
void MainWindow::DBconnectAndCreateTable()
{
DB = QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动
DB.setDatabaseName("../familyDb.db"); //设置数据库名
if (!DB.open()) //打开数据库
{
qDebug()<<"数据库无法打开!";
return ;
}
else
{
qDebug()<<"数据库成功打开!";
}
QSqlQuery query;
//家庭成员基本信息,包括姓名,年龄,性别,出生日期,身高,体重,以及账号,密码。
query.exec("create table familyBase(name varchar(20), age int, sex varchar(4),"
"BirthTime varchar(40), tall int, height int, "
"Username varchar(50), Password varchar(50));");
//家庭收入项目,包括工资,租金,股息利息,社会福利,以及其他
query.exec("create table familyIn(wage varchar(50), "
"rent varchar(50), Interest varchar(50), welfare varchar(50),"
"others varchar(50));");
//家庭支出项目,包括食品,生活用品,交通,住房,教育,医疗保健以及其他
query.exec("create table familyOut(food varchar(50), "
"life varchar(50), traffic varchar(50), house varchar(50),"
"educate varchar(50), Medical varchar(50), others varchar(50));");
//家庭收支信息,包括日期,收支人姓名,收支项目,金额
query.exec("create table familyIOInfo(IODate varchar(20), name varchar(20), "
"Items varchar(30), MoneyAmount double);");
//日期表的创建,方便根据日期加载TreeWidget
query.exec("create table DateTable(IODate varchar(20));");
}
void MainWindow::TreeWidgetsItemChanged(QTreeWidgetItem* Item, int column)
{
QSqlQuery query(DB);
// QString sqlOp;
// if(Item->parent() == nullptr)
// sqlOp = QString("select Items,MoneyAmount from familyIOInfo where IODate = '%1'").arg(Item->text(column));
// else
// sqlOp = QString("select Items,MoneyAmount from familyIOInfo where IODate = '%1' and name = '%2'").arg(Item->parent()->text(0)).arg(Item->text(column));
// if(!query.exec(sqlOp))
// qDebug() << query.lastError();
PrintInModel = new QSqlTableModel(this);
PrintOutModel = new QSqlTableModel(this);
PrintInModel->setTable("familyIOInfo");
PrintOutModel->setTable("familyIOInfo");
if(Item->parent() == nullptr)
{
PrintInModel->setFilter(QString("IODate = '%1' and MoneyAmount > 0").arg(Item->text(column))); //根据日期进行筛选
PrintOutModel->setFilter(QString("IODate = '%1' and MoneyAmount < 0").arg(Item->text(column))); //根据日期进行筛选
}
else
{
PrintInModel->setFilter(QString("IODate = '%1' and name = '%2' and MoneyAmount > 0").arg(Item->parent()->text(column)).arg(Item->text(column))); //根据日期和姓名进行筛选
PrintOutModel->setFilter(QString("IODate = '%1' and name = '%2' and MoneyAmount < 0").arg(Item->parent()->text(column)).arg(Item->text(column))); //根据日期和姓名进行筛选
}
PrintInModel->select(); //显示结果
ui->InPrintView->setModel(PrintInModel);
PrintOutModel->select(); //显示结果
ui->OutPrintView->setModel(PrintOutModel);
if(Item->parent() == nullptr)
{
ui->InPrintView->setColumnHidden(0,true); //选中日期时,表中不应隐藏姓名
ui->OutPrintView->setColumnHidden(0,true); //选中日期时,表中不应隐藏姓名
}
else
{
ui->InPrintView->setColumnHidden(0,true);
ui->InPrintView->setColumnHidden(1,true); //选中姓名时,就可以隐藏姓名
ui->OutPrintView->setColumnHidden(0,true);
ui->OutPrintView->setColumnHidden(1,true); //选中姓名时,就可以隐藏姓名
}
PrintInModel->setHeaderData(1, Qt::Horizontal, "姓名");
PrintInModel->setHeaderData(2, Qt::Horizontal, "项目");
PrintInModel->setHeaderData(3, Qt::Horizontal, "金额");
PrintOutModel->setHeaderData(1, Qt::Horizontal, "姓名");
PrintOutModel->setHeaderData(2, Qt::Horizontal, "项目");
PrintOutModel->setHeaderData(3, Qt::Horizontal, "金额");
//设置收入lineEdit和支出lineEdit
int InRowNum = PrintInModel->rowCount();
int OutRowNum = PrintOutModel->rowCount();
double InValueSum = 0;
double OutValueSum = 0;
for(int i= 0; i < InRowNum; i++)
{
QModelIndex InIndex = PrintInModel->index(i,3);
InValueSum += PrintInModel->data(InIndex).toDouble();
}
for(int i= 0; i < OutRowNum; i++)
{
QModelIndex OutIndex = PrintOutModel->index(i,3);
OutValueSum += PrintOutModel->data(OutIndex).toDouble();
}
qDebug() << InValueSum << OutValueSum;
ui->InLineEdit->setText(QString::number(InValueSum));
ui->OutLineEdit->setText(QString::number(OutValueSum));
}
void MainWindow::on_pushButton_clicked()
{ //查找月份
QSqlQuery query(DB); //使用DB数据库连接
query.exec("select * from DateTable");
int count = 0;
while(query.next())
{
if(ui->dateEdit->text() == query.value(0).toString())
{
emit ui->treeWidget->itemClicked(ui->treeWidget->topLevelItem(count), 0);
ui->treeWidget->clearSelection();
ui->treeWidget->topLevelItem(count)->setSelected(true);
return;
}
count++;
}
QMessageBox::warning(this, "提示", "查找失败", QMessageBox::Ok);
}
信息录入窗口实现:
ui界面如下:
- 通过Combox下拉框显示收支项目,右边double spinbox输入金额,如果用户切换到其他项目,则已更改的项目的字体会切换为橙色,表示已经更改。
- 通过上方的成员姓名下拉框加载需要录入信息的成员姓名,同时,通过更改输入格式的DateEdit输入录入的月份。
- 以上全部信息录入到数据库。
具体代码如下:
infoentry.h
#ifndef INFOENTRY_H
#define INFOENTRY_H
#include <QDialog>
#include <QtSql>
#include <QDataWidgetMapper>
#include <QSqlRecord>
#include <QSqlError>
#include <QSqlQuery>
#include <QMessageBox>
#include <QCompleter>
#include <QStringList>
#include <QDateTime>
#include <QPalette>
#include <QStandardItemModel>
#include <QDebug>
#include <QVariantList>
struct FamilyIOInfo
{
QString Name; //姓名字段储存
QStringList *InItemStringList; //收入项目列表
QVariantList *InValuesList; //收入项目值
QStringList *OutItemStringList;//支出项目列表
QVariantList *OutValuesList; //支出项目值
FamilyIOInfo(QString &name, QStringList* &InStrings, QVariantList* &InValue, QStringList* &OutStrings, QVariantList* &OutValue)
{
Name = name;
InItemStringList = InStrings;
InValuesList = InValue;
OutItemStringList = OutStrings;
OutValuesList = OutValue;
}
};
namespace Ui {
class InfoEntry;
}
class InfoEntry : public QDialog
{
Q_OBJECT
public:
explicit InfoEntry(QWidget *parent = nullptr);
~InfoEntry();
bool createConnection(); //创建数据库链接
void setCombox(); //设置下拉框字段
void updateFamilyDb(); //根据输入金额更新数据库
void InitialFamily(); //初始化家庭成员收支信息储存结构体family
private:
Ui::InfoEntry *ui;
QStringList *InItemstrings; //收入项目列表
QVariantList *InValues; //收入项目值
QStringList *OutItemstrings;//支出项目列表
QVariantList *OutValues; //支出项目值
int InCurrentIndex[5] = {0, 0, 0, 0, 0}; //保存收入下拉框目前index
int OutCurrentIndex[7] = {0, 0, 0, 0, 0, 0, 0}; //保存支出下拉框目前index
bool InSpinBoxIsChange[5] = {false, false, false, false, false}; //设置输入项目Spinbox更改标志
bool OutSpinBoxIsChange[7] = {false, false, false, false, false, false, false}; //设置输出项目SpinBox更改标志
QSqlDatabase DB; //数据库连接
QStandardItemModel *pItemModel; //通过model设置下拉框文本颜色
private slots:
void on_SureButton_clicked(); //确定按钮槽函数
void on_CancelButton_clicked(); //取消按钮槽函数
void on_WageComboBox_currentIndexChanged(const QString &arg1); //工资下拉框字段改变反应
void on_RentComboBox_currentIndexChanged(int index); //租金下拉框字段改变反应
void on_InterestComboBox_currentIndexChanged(int index); //股息利息下拉框字段改变反应
void on_WelfareComboBox_currentIndexChanged(int index); //社会福利下拉框字段改变反应
void on_InOtherComboBox_currentIndexChanged(int index); //收入其他项下拉框字段改变反应
void on_FoodComboBox_currentIndexChanged(int index); //食品下拉框字段改变反应
void on_LifeUseComboBox_currentIndexChanged(int index); //生活用品下拉框字段改变反应
void on_TrafficComboBox_currentIndexChanged(int index); //交通下拉框字段改变反应
void on_HouseComboBox_currentIndexChanged(int index); //住房下拉框字段改变反应
void on_EducateComboBox_currentIndexChanged(int index); //教育下拉框字段改变反应
void on_MedicalComboBox_currentIndexChanged(int index); //医疗保健下拉框字段改变反应
void on_OutOtherComboBox_currentIndexChanged(int index); //支出其他项目下拉框字段改变反应
void on_WageSpinBox_valueChanged(double arg1);
void on_RentSpinBox_valueChanged(double arg1);
void on_InterestSpinBox_valueChanged(double arg1);
void on_WelfareSpinBox_valueChanged(double arg1);
void on_InOtherSpinBox_valueChanged(double arg1);
void on_FoodSpinBox_valueChanged(double arg1);
void on_LifeUseSpinBox_valueChanged(double arg1);
void on_TrafficSpinBox_valueChanged(double arg1);
void on_HouseSpinBox_valueChanged(double arg1);
void on_EducateSpinBox_valueChanged(double arg1);
void on_MedicalSpinBox_valueChanged(double arg1);
void on_OutOtherSpinBox_valueChanged(double arg1);
};
#endif // INFOENTRY_H
infoentry.cpp
void InfoEntry::setCombox()
{ //设置下拉框字段
//设置收入项目字段
QSqlQuery InQuery(DB);
InQuery.exec("select * from familyIn");
QSqlRecord InRecord = InQuery.record();
InItemstrings = new QStringList[InRecord.count()];
InValues = new QVariantList[InRecord.count()];
while(InQuery.next())
{
for(int i = 0; i < InRecord.count(); i++)
{
if(InQuery.value(i).toString() != "")
{
InItemstrings[i] << InQuery.value(i).toString();
InValues[i].append(0.0);
}
}
}
ui->WageComboBox->clear();
ui->WageComboBox->addItems(InItemstrings[0]);
ui->WageComboBox->setCurrentIndex(0);
ui->RentComboBox->clear();
ui->RentComboBox->addItems(InItemstrings[1]);
ui->RentComboBox->setCurrentIndex(0);
ui->InterestComboBox->clear();
ui->InterestComboBox->addItems(InItemstrings[2]);
ui->InterestComboBox->setCurrentIndex(0);
ui->WelfareComboBox->clear();
ui->WelfareComboBox->addItems(InItemstrings[3]);
ui->WelfareComboBox->setCurrentIndex(0);
ui->InOtherComboBox->clear();
ui->InOtherComboBox->addItems(InItemstrings[4]);
ui->InOtherComboBox->setCurrentIndex(0);
//设置支出项目字段
QSqlQuery queryOut(DB);
queryOut.exec("select * from familyOut");
QSqlRecord OutRecord = queryOut.record();
OutItemstrings = new QStringList[OutRecord.count()];
OutValues = new QVariantList[OutRecord.count()];
while(queryOut.next())
{
for(int i = 0; i < OutRecord.count(); i++)
{
if(queryOut.value(i).toString() != "")
{
OutItemstrings[i] << queryOut.value(i).toString();
OutValues[i].append(0.0);
}
}
}
ui->FoodComboBox->clear();
ui->FoodComboBox->addItems(OutItemstrings[0]);
ui->FoodComboBox->setCurrentIndex(0);
ui->LifeUseComboBox->clear();
ui->LifeUseComboBox->addItems(OutItemstrings[1]);
ui->LifeUseComboBox->setCurrentIndex(0);
ui->TrafficComboBox->clear();
ui->TrafficComboBox->addItems(OutItemstrings[2]);
ui->TrafficComboBox->setCurrentIndex(0);
ui->HouseComboBox->clear();
ui->HouseComboBox->addItems(OutItemstrings[3]);
ui->HouseComboBox->setCurrentIndex(0);
ui->EducateComboBox->clear();
ui->EducateComboBox->addItems(OutItemstrings[4]);
ui->EducateComboBox->setCurrentIndex(0);
ui->MedicalComboBox->clear();
ui->MedicalComboBox->addItems(OutItemstrings[5]);
ui->MedicalComboBox->setCurrentIndex(0);
ui->OutOtherComboBox->clear();
ui->OutOtherComboBox->addItems(OutItemstrings[6]);
ui->OutOtherComboBox->setCurrentIndex(0);
//设置姓名字段
QSqlQuery query(DB);
query.exec("select * from familyBase");
QSqlRecord record = query.record();
QStringList stringList;
while(query.next())
{
if(query.value(0).toString() != "")
stringList << query.value(0).toString();
}
ui->NameComboBox->addItems(stringList);
}
void InfoEntry::on_SureButton_clicked()
{ //确定按钮槽函数
if(QMessageBox::question(this, "提问" , "确定更改吗") == QMessageBox::Yes)
{
//保存目前收入项目的值
InValues[0].replace(InCurrentIndex[0], ui->WageSpinBox->value()); //储存该值
InValues[1].replace(InCurrentIndex[1], ui->RentSpinBox->value()); //储存该值
InValues[2].replace(InCurrentIndex[2], ui->InterestSpinBox->value()); //储存该值
InValues[3].replace(InCurrentIndex[3], ui->WelfareSpinBox->value()); //储存该值
InValues[4].replace(InCurrentIndex[4], ui->InOtherSpinBox->value()); //储存该值
//保存目前支出项目的值
OutValues[0].replace(OutCurrentIndex[0], ui->FoodSpinBox->value()); //储存该值
OutValues[1].replace(OutCurrentIndex[1], ui->LifeUseSpinBox->value()); //储存该值
OutValues[2].replace(OutCurrentIndex[2], ui->InterestSpinBox->value()); //储存该值
OutValues[3].replace(OutCurrentIndex[3], ui->HouseSpinBox->value()); //储存该值
OutValues[4].replace(OutCurrentIndex[4], ui->EducateSpinBox->value()); //储存该值
OutValues[5].replace(OutCurrentIndex[5], ui->MedicalSpinBox->value()); //储存该值
OutValues[6].replace(OutCurrentIndex[6], ui->OutOtherSpinBox->value()); //储存该值
//保存即将存入数据库中的数据,他们包括
//Items:收支项目
//Values:对应金额
//FamilyName:收支人姓名
//DateString:收支日期
QStringList Items; //收支项目
QVariantList Values; //对应金额
QStringList DateString; //储存日期
QStringList FamilyName; //姓名字段储存
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < InValues[i].length(); j++)
{
if(InValues[i][j] != 0)
{
FamilyName << ui->NameComboBox->currentText();
DateString << ui->dateEdit->text();
Items << InItemstrings[i][j];
Values << InValues[i][j].toDouble();
}
}
}
for(int i = 0; i < 7; i++)
{
for(int j = 0; j < OutValues[i].length(); j++)
{
if(OutValues[i][j] != 0)
{
FamilyName <<ui->NameComboBox->currentText();
DateString << ui->dateEdit->text();
Items << OutItemstrings[i][j];
Values << -OutValues[i][j].toDouble(); //支出项目变成支出形式(即负数)
}
}
}
//判断空否,若空则未做修改,给出提示框
if(Items.isEmpty())
{
if(QMessageBox::warning(this, "警告", "您并未进行修改,请问是否继续修改?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
return;
else
this->close();
}
//将数据写入数据库
QSqlQuery query(DB);
//写入到日期表
query.exec("select * from DateTable");
//QSqlRecord Record = query.record();
//qDebug() << Record.count();
//将日期存入日期表
QStringList NewDateList;
query.next();
if(query.value(0).toString() == "") //表空则直接插入
{
qDebug() << "这个表是空的";
NewDateList << ui->dateEdit->text();
query.prepare("insert into DateTable(IODate) values(:IODate)");
query.bindValue(0, NewDateList);
if(!query.exec())
qDebug() << query.lastError();
}
else
{ //不空则按顺序插入
qDebug() << "进来了";
query.previous();
int tableLength = 0;
while(query.next())
{
tableLength++;
NewDateList.insert(tableLength - 1, query.value(0).toString());
}
for(int i = 0; i < tableLength; i++)
{
if(NewDateList[i].compare(ui->dateEdit->text()) < 0)
{
NewDateList.insert(i,ui->dateEdit->text());
break;
}
}
qDebug() << NewDateList;
query.prepare("delete from DateTable");
if(!query.exec())
qDebug() << query.lastError();
query.prepare("insert into DateTable(IODate) values(:IODate)");
query.addBindValue(NewDateList);
if(!query.execBatch())
qDebug() << query.lastError();
}
//写入到家庭收支信息表
query.prepare("insert into familyIOInfo(IODate, name, Items, MoneyAmount) values(:IODate, :name, :Items, :MoneyAmount)");
query.addBindValue(DateString); //写入日期
query.addBindValue(FamilyName); //写入姓名
query.addBindValue(Items); //写入项目
query.addBindValue(Values); //写入对应金额
if(!query.execBatch())
qDebug() << query.lastError();
this->close();
}
else
return;
}
void InfoEntry::on_WageComboBox_currentIndexChanged(const QString &arg1)
{ //工资下拉框字段改变反应
if(InSpinBoxIsChange[0] == true)
{
int OldIndex = InCurrentIndex[0];
pItemModel = qobject_cast<QStandardItemModel*>(ui->WageComboBox->model());
pItemModel->item(OldIndex)->setForeground(QColor(255, 97, 0)); //修改文本颜色
InValues[0].replace(OldIndex, ui->WageSpinBox->value()); //储存该值
InCurrentIndex[0] = ui->WageComboBox->findText(arg1);
ui->WageSpinBox->setValue(InValues[0][ui->WageComboBox->findText(arg1)].toDouble());
InSpinBoxIsChange[0] = false;
return;
}
else
{
ui->WageSpinBox->setValue(InValues[0][ui->WageComboBox->findText(arg1)].toDouble());
InSpinBoxIsChange[0] = false;
return;
}
}
void InfoEntry::on_WageSpinBox_valueChanged(double arg1)
{
InSpinBoxIsChange[0] = true;
}
普通用户窗口
- 该窗口类似于管理员窗口,只需要根据登录窗口获取用户账号,显示用户信息。并将View设置为不可编辑。
界面如下:
具体代码如下:
subwindow.h
#ifndef SUBWINDOW_H
#define SUBWINDOW_H
#include <QMainWindow>
#include <QSqlDatabase>
#include <QTreeWidgetItem>
#include <QSqlTableModel>
#include <QDate>
#include <QMessageBox>
#include <QProcess>
#include <QDir>
#include <QSqlError>
#include <QDialog>
#include "changepassword.h"
namespace Ui {
class SubWindow;
}
class SubWindow : public QMainWindow
{
Q_OBJECT
public:
explicit SubWindow(QWidget *parent = nullptr);
~SubWindow();
void setUserName(QString user){
userName = user;
}
public slots:
void CheckMonth(); //月份查找响应槽函数
void TreeWidgetsItemChanged(QTreeWidgetItem*, int); //点击treewidget
private slots:
void on_dateEdit_userDateChanged(const QDate &date);
void SignOut(); //登出
void ChangePwd(); //修改密码
void on_pushButton_clicked();
void ShowCopyRight(); //版权:谭俊杰
private:
Ui::SubWindow *ui;
QSqlDatabase DB;//数据库连接
QString name; //用户姓名(非账号)
QString userName; //用户账号
QDate CheckDate; //查找月份
QSqlTableModel *PrintInModel; //收入项目模型
QSqlTableModel *PrintOutModel; //支出项目模型
double InValueSum; //收入项目总值
double OutValueSum; //支出项目总值
void InitUI(); //初始化界面
void InitialNameAndTitle(); //初始化用户名与窗口标题
};
#endif // SUBWINDOW_H
subwindow.cpp
void SubWindow::TreeWidgetsItemChanged(QTreeWidgetItem *Item, int column)
{
PrintInModel->setTable("familyIOInfo");
PrintInModel->setFilter(QString("IODate = '%1' and name = '%2' and MoneyAmount > 0").arg(Item->text(column)).arg(name)); //根据日期和姓名进行筛选
PrintInModel->select(); //读取数据库
//PrintInModel->removeColumn(0); //隐藏日期列
//PrintInModel->removeColumn(1); //隐藏姓名列
ui->PrintInItemsView->setModel(PrintInModel);
ui->PrintInItemsView->setColumnHidden(0,true);
ui->PrintInItemsView->setColumnHidden(1,true);
PrintOutModel->setTable("familyIOInfo");
PrintOutModel->setFilter(QString("IODate = '%1' and name = '%2' and MoneyAmount < 0").arg(Item->text(column)).arg(name)); //根据日期和姓名进行筛选
PrintOutModel->select(); //显示结果
//PrintOutModel->removeColumn(0); //隐藏日期列
//PrintOutModel->removeColumn(1); //隐藏姓名列
ui->PrintOutItemsView->setModel(PrintOutModel);
ui->PrintOutItemsView->setColumnHidden(0,true);
ui->PrintOutItemsView->setColumnHidden(1,true);
//更改model
PrintInModel->setHeaderData(2, Qt::Horizontal, "收入项目");
PrintInModel->setHeaderData(3, Qt::Horizontal, "金额");
PrintOutModel->setHeaderData(2, Qt::Horizontal, "支出项目");
PrintOutModel->setHeaderData(3, Qt::Horizontal, "金额");
int InRowNum = PrintInModel->rowCount();
int OutRowNum = PrintOutModel->rowCount();
InValueSum = 0;
OutValueSum = 0;
for(int i= 0; i < InRowNum; i++)
{
QModelIndex InIndex = PrintInModel->index(i,3);
InValueSum += PrintInModel->data(InIndex).toDouble();
}
for(int i= 0; i < OutRowNum; i++)
{
QModelIndex OutIndex = PrintOutModel->index(i,3);
OutValueSum += PrintOutModel->data(OutIndex).toDouble();
}
qDebug() << InValueSum << OutValueSum;
ui->InlineEdit->setText(QString::number(InValueSum));
ui->OutlineEdit->setText(QString::number(OutValueSum));
}
void SubWindow::InitialNameAndTitle()
{
QString userName;
//指定文件
QFile file( "../UserNameFile.txt" );
//指定为GBK
QTextCodec *codec = QTextCodec::codecForName("GBK");
//如果打开文件失败,直接退出
if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
return;
//当未到达文件结束位置
while(!file.atEnd())
{
//读取一行文本数据
QByteArray line = file.readLine();
//将读取到的行数据转换为Unicode
userName = codec->toUnicode(line);
}
file.close();
if(QFile::remove("../UserNameFile.txt")) //删除用于信息传递的文件
qDebug() << "你已删除文件!";
else
qDebug() << "文件未删除";
DB = QSqlDatabase::addDatabase("QSQLITE"); //添加 SQL LITE数据库驱动
DB.setDatabaseName("../familyDb.db"); //设置数据库名
if (!DB.open()) //打开数据库
{
qDebug()<<"数据库无法打开!";
return ;
}
else
{
qDebug()<<"数据库成功打开!";
}
QSqlQuery query(DB);
QString sqlOp = QString("select * from familyBase where Username = '%1'").arg(userName);
query.exec(sqlOp);
while (query.next())
{
qDebug() << query.value(0).toString();
if(query.value(6).toString() == userName)
{
name = query.value(0).toString();
this->setWindowTitle("用户:"+name);
break;
}
}
}
系统测试情况:
- 经测试,系统运行无强制退出错误,且实现基本功能,未发现bug。
系统的优点与改进:
- 优点:通过TreeWidget将成员信息显示,更加清晰明了。
- 优点:添加了退出登录计算金额总量功能,方便用户查看信息。
- 改进:界面设计不足:单调切无图标,背景等,可以在这方面进行优化
- 改进:在对话框信息返回时由于初始思路匮乏以及Qt传递QString信息错误,使用了临时文件储存信息的方法,其实可以使用指针。
感想:
通过这样一个程序,真正初步认识带有图形界面的windows应用程序开发。明白了qt的信号和槽机制,以及qt的控件和储存结构的相关知识,让我更加产生进行更强大系统功能实现的兴趣。
上一篇: Angularjs过滤器使用详解
下一篇: C#在线运行
推荐阅读
-
基于C++ Qt实现的红色警戒3修改器(Github开源)
-
QT5:C++实现基于multimedia的音乐播放器(二)
-
QT5:C++实现基于multimedia的音乐播放器(一)
-
基于SSH+shiro+solr的家庭记账系统
-
Thymeleaf+SpringBoot+Mybatis实现的家庭财务管理系统
-
C++框架_之Qt的窗口部件系统的详解-上
-
QT5:C++实现基于Multimedia的音乐播放器(序)
-
苹果自曝全新OS:基于家庭的操作系统
-
基于Cmake+QT+VS的C++项目构建开发编译简明教程
-
基于Qt平台的报表解决方案NCReport v2.18.0发布【附下载】 qt报表解决方案报表c++