项目介绍
这次练习的项目是汽车信息管理系统,项目参考Qt5开发及实例(第3版)中的汽车销售管理系统,写到博客上的目的是为了梳理自己的思路,所以代码很大程度上是参照书上的实例。
项目实现了车辆与销售的的管理,运行程序出现登录界面,输入正确的密码才能登录,进入主界面后有两个菜单,【销售管理】和【修改密码】,【销售管理】菜单下有三个子菜单,【车辆管理】、【销售统计】、【退出】。其中车辆信息使用数据库进行存储,销售记录使用XML文档存储。
功能实现
车辆管理界面右侧的List Widget部件用来显示每天的销售记录,销售记录的保存方式使用XML文件记录。
1.创建XML文件
首先在"connection.h"文件中添加一个创建XML文件的函数。代码如下:
static bool createXml(){
QFile file("data.xml");
//判断文件是否存在,如果存在返回true
if(file.exists())return true;
//判断文件是否是只写或者是覆盖的,如果不是,则返回false
if(!file.open(QIODevice::WriteOnly|QIODevice::Truncate))return false;
//定义一个Xml文档
QDomDocument doc;
//写入Xml文档头部
QDomProcessingInstruction instruction;//添加处理命令
instruction = doc.createProcessingInstruction("xml","version = \"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instruction);
//添加根节点
QDomElement root = doc.createElement(QString(QObject::tr("DailySalesList")));
doc.appendChild(root);
//输出到文件
QTextStream out(&file);
doc.save(out,4);//缩进4格
file.close();
return true;
}
并且在main函数中添加下面一行代码,用来判断XML文件是否创建成功,所有代码的最前面:
if(!createConnection()||!createXml()) return 0;
2.获取时间日期
在"widget.h"文件中定义一个public函数和枚举变量用来获取时间日期,并在"widget.cpp"文件中实现函数:
//定义一个枚举变量和public函数,用来获取当前的时间和日期
enum DateTimeType{Time,Date,DateTime};
QString getDateTime(DateTimeType type);
//获取时间和日期
QString Widget::getDateTime(DateTimeType type){
QDateTime datetime = QDateTime::currentDateTime();
QString date = datetime.toString("yyyy-MM-dd");
QString time = datetime.toString("hh:mm");
QString dateAndTime = datetime.toString("yyyy-MM-dd dddd hh:mm");
if(type == Date)return date;
else if(type == Time)return time;
else return dateAndTime;
}
3.读写XML文件
在"widget.h"文件中定义读取和写入XML文件的函数,并在"widget.cpp"文件中实现,具体如下:
//读取XML文档
bool Widget::docRead(){
QFile file("data.xml");
if(!file.open(QIODevice::ReadOnly))
return false;
if(!doc.setContent(&file)){
file.close();
return false;
}
file.close();
return true;
}
//写入XML文档
bool Widget::docWrite(){
QFile file("data.xml");
if(!file.open(QIODevice::WriteOnly|QIODevice::Truncate))
return false;
QTextStream out(&file);
//将节点及其所有子节点的XML表示形式写入流
doc.save(out,4);
file.close();
return true;
}
4.修改XML文档
首先实现创建节点函数,代码如下:
//创建节点
void Widget::createNodes(QDomElement &date){
//创建一个Time节点
QDomElement time = doc.createElement(QString("Time"));
//添加一个time属性
QDomAttr curTime = doc.createAttribute(QString("time"));
//将time属性的值设置为获取到的时间
curTime.setValue(getDateTime(Time));
//将time属性赋给Time节点
time.setAttributeNode(curTime);
//将节点添加到XML文件中
date.appendChild(time);
//创建下面几个节点
QDomElement factory = doc.createElement(QString("Factory"));
QDomElement brand = doc.createElement(QString("Brand"));
QDomElement price = doc.createElement(QString("Price"));
QDomElement num = doc.createElement(QString("Num"));
QDomElement sum = doc.createElement(QString("Sum"));
QDomText text;
//创建文本节点,并添加到上面创建的节点当中
text = doc.createTextNode(
QString("%1").arg(ui->sellFactoryComboBox->currentText()));
factory.appendChild(text);
text = doc.createTextNode(
QString("%1").arg(ui->sellBrandComboBox->currentText()));
brand.appendChild(text);
text = doc.createTextNode(
QString("%1").arg(ui->sellPriceLineEdit->text()));
price.appendChild(text);
text = doc.createTextNode(
QString("%1").arg(ui->sellNumSpinBox->value()));
num.appendChild(text);
text = doc.createTextNode(
QString("%1").arg(ui->sellSumLineEdit->text()));
sum.appendChild(text);
//将上面的几个节点,添加到time节点中
time.appendChild(factory);
time.appendChild(brand);
time.appendChild(price);
time.appendChild(num);
time.appendChild(sum);
}
接下来实现修改XML文档的函数,作用是售车成功的时候被调用,将销售信息添加到XML文档中,实现如下:
//修改XML文档
void Widget::writeXml(){
//从文件读取
if(docRead()){
QString currentDate = getDateTime(Date);
QDomElement root = doc.documentElement();
//根据是否有日期节点进行处理
if(!root.hasChildNodes()){
QDomElement date = doc.createElement(QString("Date"));
QDomAttr curDate = doc.createAttribute("date");
curDate.setValue(currentDate);
date.setAttributeNode(curDate);
root.appendChild(date);
createNodes(date);
}else{
QDomElement date = root.lastChild().toElement();
//根据是否已经有今天的日期节点进行处理
if(date.attribute("date") == currentDate){
createNodes(date);
}else{
QDomElement date = doc.createElement(QString("Date"));
QDomAttr curDate = doc.createAttribute("date");
curDate.setValue(currentDate);
date.setAttributeNode(curDate);
root.appendChild(date);
createNodes(date);
}
}
//写入文件
docWrite();
}
}
5.显示销售清单
添加读取XML文档中当天销售记录并显示到页面上的函数,实现如下:
void Widget::showDailyList(){
ui->dailyList->clear();
if(docRead()){
QDomElement root = doc.documentElement();
QString title = root.tagName();
QListWidgetItem *titleItem = new QListWidgetItem;
titleItem->setText(QString("-----%1-----").arg(title));
titleItem->setTextAlignment(Qt::AlignCenter);
ui->dailyList->addItem(titleItem);
if(root.hasChildNodes()){
QString currentDate = getDateTime(Date);
QDomElement dateElement = root.lastChild().toElement();
QString date = dateElement.attribute("date");
if(date == currentDate){
ui->dailyList->addItem("");
ui->dailyList->addItem(QString(QObject::tr("date:")+"%1").arg(date));
ui->dailyList->addItem("");
QDomNodeList children = dateElement.childNodes();
//遍历当日销售的所有汽车
for(int i = 0;i<children.count();i++){
QDomNode node = children.at(i);
QString time = node.toElement().attribute("time");
QDomNodeList list = node.childNodes();
QString factory = list.at(0).toElement().text();
QString brand = list.at(1).toElement().text();
QString price = list.at(2).toElement().text();
QString num = list.at(3).toElement().text();
QString sum = list.at(4).toElement().text();
QString str = time + QObject::tr("sell") + brand + factory + " " +
num + QObject::tr("units") + QObject::tr("transaction price:")
+ price + QObject::tr("ten thousand,in all") + sum + QObject::tr("ten thousand");
QListWidgetItem *tempItem = new QListWidgetItem;
tempItem->setText("****************************");
tempItem->setTextAlignment(Qt::AlignCenter);
ui->dailyList->addItem(tempItem);
ui->dailyList->addItem(str);
}
}
}
}
}
然后在on_sellOkBtn_clicked()函数中添加下面两行代码:
//成功则弹出提示信息
QSqlDatabase::database().commit();
QMessageBox::information(this,tr("Tip"),tr("Successful car purchase"),QMessageBox::Ok);
//添加这两行代码,注意位置
writeXml();
showDailyList();
//并将页面恢复到初始状态
on_sellCancelBtn_clicked();
并在构造函数中调用showDailyList函数,写在最后就行:
showDailyList();
6.更新翻译文件
更新翻译文件,并根据实际情况进行翻译,因为中文乱码的问题,所以我基本上是把所有的中文都通过翻译文件的方式去显示的。
看一下效果:
因为春节的关系,可能更新速度会比较慢,最近也是忙的头晕呀,不过学习还是得坚持的。