工程源码下载地址
https://download.csdn.net/download/guoyunfei123/12262949
参考《Qt及Qt Quick开发实战精解》
操作
登录界面
商品管理界面
销售统计
修改密码
主要程序代码
connection.h
#ifndef CONNECTION_H
#define CONNECTION_H
#include <QtSql>
#include <QDebug>
#include <QDomDocument>
static bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setHostName("yafeilinux");
db.setDatabaseName("data.db");
db.setUserName("yafei");
db.setPassword("123456");
if(!db.open())
{
//提示出错
return false;
}
QSqlQuery query;
//创建分类表
query.exec("create table type(id varchar primary key, name varchar)");
query.exec(QString("insert into type values ('0', '请选择类型')"));
query.exec(QString("insert into type values ('01', '电视')"));
query.exec(QString("insert into type values('02', '空调')"));
//创建品牌表
query.exec("create table brand(id varchar primary key, name varchar, type varchar, price int, sum int, sell int, last int)");
query.exec(QString("insert into brand values('01', '海信', '电视', 3699, 50, 10, 40)"));
query.exec(QString("insert into brand values('02', '创维', '电视', 3499, 20, 5, 15)"));
query.exec(QString("insert into brand values('03', '海尔', '电视', 4199, 80, 40, 40)"));
query.exec(QString("insert into brand values('04', '王牌', '电视', 3999, 40, 10, 30)"));
query.exec(QString("insert into brand values('05', '海尔', '空调', 2899, 60, 10, 50)"));
query.exec(QString("insert into brand values('06', '格力', '空调', 1799, 70, 20, 50)"));
//创建密码表
query.exec("create table password(pwd varchar primary key)");
query.exec(QString("insert into password values('123456')"));
return true;
}
static bool createXml()
{
QFile file("data.xml");
if(file.exists())
{
return true;
}
if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
return false;
}
QDomDocument doc;
QDomProcessingInstruction instruction;
instruction = doc.createProcessingInstruction(
"xml", "version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instruction);
QDomElement root = doc.createElement(QString("日销售清单"));
doc.appendChild(root);
QTextStream out(&file);
doc.save(out, 4);
file.close();
return true;
}
#endif // CONNECTION_H
main.cpp
#include <QTextCodec>
#include "widget.h"
#include "connection.h"
#include "logindialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());
if(!createConnection() || !createXml())
{
qDebug() <<"不能连接数据库";
return false;
}
Widget w;
LoginDialog dialog;
if(dialog.exec() == QDialog::Accepted)
{
w.show();
return a.exec();
}
else
{
return 0;
}
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QDomDocument>
#include <QStandardItemModel>
#include <QWidget>
class QStandardItemModel;
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
enum DateTimeType
{
Time,
Date,
DateTime
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
QString getDateTime(DateTimeType type);
private slots:
void on_sellTypeComboBox_currentIndexChanged(const QString &type);
void on_sellBrandComboBox_currentIndexChanged(const QString &brand);
void on_sellNumSpinBox_valueChanged(int value);
void on_sellCancelBtn_clicked();
void on_sellOkBtn_clicked();
void on_typeComboBox_currentIndexChanged(const QString &type);
void on_updateBtn_clicked();
void on_manageBtn_clicked();
void on_chartBtn_clicked();
void on_passwordBtn_clicked();
void on_pwdOkBtn_clicked();
void on_pwdCancelBtn_clicked();
private:
Ui::Widget *ui;
QDomDocument doc;
QStandardItemModel *chartModel;
bool docRead();
bool docWrite();
void writeXml();
void createNodes(QDomElement &date);
void showDailyList();
void createChartModelView();
void showChart();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "connection.h"
#include <QMessageBox>
#include <QSplitter>
#include <QTableView>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setFixedSize(750, 500);
// ui->stackedWidget->setCurrentIndex(0);
QSqlQueryModel *typeModel = new QSqlQueryModel(this);
typeModel->setQuery("select name from type");
ui->sellTypeComboBox->setModel(typeModel);
// QSplitter *splitter = new QSplitter(ui->managePage);
// splitter ->resize(700, 360);
// splitter->move(0, 50);
// splitter->addWidget(ui->toolBox);
// splitter->addWidget(ui->dailyList);
// splitter->setStretchFactor(0, 1);
// splitter->setStretchFactor(1, 1);
ui ->typeComboBox ->setModel(typeModel);
createChartModelView();
}
Widget::~Widget()
{
delete ui;
}
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;
}
}
void Widget::on_sellTypeComboBox_currentIndexChanged(const QString &type)
{
if(type == "请选择类型")
{
//进行其他部件的状态设置
on_sellCancelBtn_clicked();
}
else
{
ui ->sellBrandComboBox ->setEnabled(true);
QSqlQueryModel *model = new QSqlQueryModel(this);
model ->setQuery(QString("select name from brand where type = '%1'").arg(type));
ui ->sellBrandComboBox ->setModel(model);
ui ->sellCancelBtn ->setEnabled(true);
}
}
void Widget::on_sellBrandComboBox_currentIndexChanged(const QString &brand)
{
ui ->sellNumSpinBox ->setValue(0);
ui ->sellNumSpinBox ->setEnabled(false);
ui ->sellSumLineEdit ->clear();
ui ->sellSumLineEdit ->setEnabled(false);
ui ->sellOkBtn ->setEnabled(false);
QSqlQuery query;
query.exec(QString("select price from brand where name = '%1' and type = '%2'").arg(brand).arg(ui ->sellTypeComboBox ->currentText()));
query.next();
ui ->sellPriceLineEdit ->setEnabled(true);
ui ->sellPriceLineEdit ->setReadOnly(true);
ui ->sellPriceLineEdit ->setText(query.value(0).toString());
query.exec(QString("select last from brand where name = '%1' and type = '%2'").arg(brand).arg(ui->sellTypeComboBox ->currentText()));
query.next();
int num = query.value(0).toInt();
if(num == 0)
{
QMessageBox::information(this, tr("提示"), tr("该商品已经售完!"), QMessageBox::Ok);
}
else
{
ui ->sellNumSpinBox ->setEnabled(true);
ui ->sellNumSpinBox ->setMaximum(num);
ui ->sellLastNumLabel ->setText(tr("剩余数量:%1").arg(num));
ui ->sellLastNumLabel ->setVisible(true);
}
}
void Widget::on_sellNumSpinBox_valueChanged(int value)
{
if(value == 0)
{
ui ->sellSumLineEdit ->clear();
ui ->sellSumLineEdit ->setEnabled(false);
ui ->sellOkBtn ->setEnabled(false);
}
else
{
ui ->sellSumLineEdit ->setEnabled(true);
ui ->sellSumLineEdit ->setReadOnly(true);
qreal sum = value * ui ->sellPriceLineEdit ->text().toInt();
ui ->sellSumLineEdit ->setText(QString::number(sum));
ui ->sellOkBtn ->setEnabled(true);
}
}
void Widget::on_sellCancelBtn_clicked()
{
ui ->sellTypeComboBox ->setCurrentIndex(0);
ui ->sellBrandComboBox ->clearEditText();
ui ->sellPriceLineEdit ->clear();
ui ->sellLastNumLabel ->setText(tr("剩余数量:000"));
ui ->sellNumSpinBox ->clear();
ui ->sellSumLineEdit ->clear();
}
void Widget::on_sellOkBtn_clicked()
{
QString type = ui ->sellTypeComboBox ->currentText();
QString name = ui ->sellBrandComboBox ->currentText();
int value = ui ->sellNumSpinBox ->value();
//cellNUmSpinBox的最大值就是以前的剩余量
int last = ui ->sellNumSpinBox ->maximum() - value;
QSqlQuery query;
query.exec(QString("select sell from brand where name = '%1' and type = '%2'").arg(name).arg(type));
query.next();
int sell = query.value(0).toInt() + value;
//事务操作
QSqlDatabase::database().transaction();
bool rtn = query.exec(QString("update brand set sell = '%1', last = '%2' where name = '%3' and type = '%4'")
.arg(sell).arg(last).arg(name).arg(type));
if(rtn)
{
QSqlDatabase::database().commit();
QMessageBox::information(this, tr("提示"), tr("购买成功!"), QMessageBox::Ok);
writeXml();
showDailyList();
on_sellCancelBtn_clicked();
}
else
{
QSqlDatabase::database().rollback();
}
}
//读取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);
doc.save(out, 4);
file.close();
return true;
}
void Widget::writeXml()
{
//先从文件读取
if(docRead())
{
QString currentDate = getDateTime(Date);
QDomElement root = doc.documentElement();
//根据是否有日期节点进行处理
if(!root.hasChildNodes())
{
QDomElement date = doc.createElement(QString("日期"));
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("日期"));
QDomAttr curDate = doc.createAttribute("date");
curDate.setValue(currentDate);
date.setAttributeNode(curDate);
root.appendChild(date);
createNodes(date);
}
}
//写入到文件
docWrite();
}
}
void Widget::createNodes(QDomElement &date)
{
QDomElement time = doc.createElement(QString("时间"));
QDomAttr curTime = doc.createAttribute("time");
curTime.setValue(getDateTime(Time));
time.setAttributeNode(curTime);
date.appendChild(time);
QDomElement type = doc.createElement(QString("类型"));
QDomElement brand = doc.createElement(QString("品牌"));
QDomElement price = doc.createElement(QString("单价"));
QDomElement num = doc.createElement(QString("数量"));
QDomElement sum = doc.createElement(QString("金额"));
QDomText text;
text = doc.createTextNode(QString("%1").arg(ui ->sellTypeComboBox ->currentText()));
type.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.appendChild(type);
time.appendChild(brand);
time.appendChild(price);
time.appendChild(num);
time.appendChild(sum);
}
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("日期:%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 type = 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 + "出售" + brand + type
+ " " + num + "台," + "单价:" + price
+ "元,共" + sum + "元";
QListWidgetItem *tempItem = new QListWidgetItem;
tempItem ->setText("******************************");
tempItem ->setTextAlignment(Qt::AlignCenter);
ui ->dailyList ->addItem(tempItem);
ui ->dailyList ->addItem(str);
}
}
}
}
}
void Widget::createChartModelView()
{
chartModel = new QStandardItemModel(this);
chartModel ->setColumnCount(3);
chartModel ->setHeaderData(0, Qt::Horizontal, QString("品牌"));
chartModel ->setHeaderData(1, Qt::Horizontal, QString("销售数量"));
chartModel ->setHeaderData(2, Qt::Horizontal, QString("剩余数量"));
QSplitter *splitter = new QSplitter(ui ->chartPage);
splitter ->resize(700, 320);
splitter ->move(0, 80);
QTableView *table = new QTableView;
// PieView *pieChart = new PieView;
splitter ->addWidget(table);
// splitter ->addWidget(pieChart);
splitter ->setStretchFactor(0, 1);
splitter ->setStretchFactor(1, 2);
splitter ->setStretchFactor(2, 3);
table ->setModel(chartModel);
// pieChart ->setModel(chartModel);
QItemSelectionModel *selectionModel = new QItemSelectionModel(chartModel);
table ->setSelectionModel(selectionModel);
// pieChart ->setSelectionModel(selectionModel);
}
void Widget::showChart()
{
QSqlQuery query;
query.exec(QString("select name, sell, last from brand where type = '%1'").arg(ui ->typeComboBox ->currentText()));
chartModel ->removeRows(0, chartModel ->rowCount(QModelIndex()), QModelIndex());
int row = 0;
while(query.next())
{
int r = qrand() %256;
int g = qrand() %256;
int b = qrand() %256;
chartModel ->insertRows(row, 1, QModelIndex());
chartModel ->setData(chartModel ->index(row, 0, QModelIndex()), query.value(0).toString());
chartModel ->setData(chartModel ->index(row, 1, QModelIndex()), query.value(1).toString());
chartModel ->setData(chartModel ->index(row, 2, QModelIndex()), query.value(2).toString());
chartModel ->setData(chartModel ->index(row, 0, QModelIndex()), QColor(r, g, b), Qt::DecorationRole);
row++;
}
}
void Widget::on_typeComboBox_currentIndexChanged(const QString &type)
{
if(type != "请选择类型")
{
showChart();
}
}
void Widget::on_updateBtn_clicked()
{
if(ui ->typeComboBox ->currentText() != "请选择类型")
{
showChart();
}
}
void Widget::on_manageBtn_clicked()
{
ui ->stackedWidget ->setCurrentIndex(0);
}
void Widget::on_chartBtn_clicked()
{
ui ->stackedWidget ->setCurrentIndex(1);
showChart();
}
void Widget::on_passwordBtn_clicked()
{
ui ->stackedWidget ->setCurrentIndex(2);
}
void Widget::on_pwdOkBtn_clicked()
{
if(ui ->oldPwdLineEdit ->text().isEmpty())
{
QMessageBox::warning(this, tr("更改密码"), tr("旧密码不能为空!"), QMessageBox::Ok);
ui ->oldPwdLineEdit ->setFocus();
}
else
{
QSqlQuery query;
query.exec(QString("select pwd from password"));
query.next();
qDebug() << query.value(0).toString();
if(query.value(0).toString() != ui ->oldPwdLineEdit ->text())
{
QMessageBox::warning(this, tr("更改密码"), tr("旧密码不对!"), QMessageBox::Ok);
ui ->oldPwdLineEdit ->setFocus();
}
else
{
if(ui ->newPwdLineEdit ->text().isEmpty()
|| ui ->newPwdLineEdit ->text() != ui ->newPwdConfirmLineEdit ->text())
{
QMessageBox::warning(this, tr("更改密码"), tr("新密码为空或者新密码和确认密码不相同"), QMessageBox::Ok);
ui ->oldPwdLineEdit ->setFocus();
}
else
{
query.exec(QString("update password set pwd = '%1'").arg(ui ->newPwdLineEdit ->text()));
QMessageBox::information(this, tr("更改密码"), tr("密码修改成功!!!"), QMessageBox::Ok);
}
}
}
}
void Widget::on_pwdCancelBtn_clicked()
{
ui ->oldPwdLineEdit ->clear();
ui ->newPwdLineEdit ->clear();
ui ->newPwdConfirmLineEdit ->clear();
}
logindialog.h
#ifndef LOGINDIALOG_H
#define LOGINDIALOG_H
#include <QDialog>
namespace Ui {
class LoginDialog;
}
class LoginDialog : public QDialog
{
Q_OBJECT
public:
explicit LoginDialog(QWidget *parent = nullptr);
~LoginDialog();
private slots:
void on_loginBtn_clicked();
void on_quitBtn_clicked();
private:
Ui::LoginDialog *ui;
};
#endif // LOGINDIALOG_H
logindialog.cpp
#include "logindialog.h"
#include "ui_logindialog.h"
#include <QMessageBox>
#include <QSqlQuery>
#include <QDebug>
LoginDialog::LoginDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::LoginDialog)
{
ui->setupUi(this);
setFixedSize(400, 300);
setWindowTitle("登录");
ui ->pwdLineEdit ->setFocus();
ui ->loginBtn ->setDefault(true);
}
LoginDialog::~LoginDialog()
{
delete ui;
}
void LoginDialog::on_loginBtn_clicked()
{
if(ui ->pwdLineEdit ->text().isEmpty())
{
QMessageBox::information(this, tr("请输入密码"), tr("请先输入密码再登录!"), QMessageBox::Ok);
ui ->pwdLineEdit ->setFocus();
}
else
{
QSqlQuery query;
query.exec("select pwd from password");
query.next();
// qDebug() << query.value(0).toString();
if(query.value(0).toString() == ui ->pwdLineEdit ->text())
{
QDialog::accept();
}
else
{
// qDebug() << ui ->pwdLineEdit ->text();
QMessageBox::warning(this, tr("密码错误"),
tr("请输入正确的密码再登录!"), QMessageBox::Ok);
ui ->pwdLineEdit ->clear();
ui ->pwdLineEdit ->setFocus();
}
}
}
void LoginDialog::on_quitBtn_clicked()
{
QDialog::reject();
}