当前位置:网站首页>QT学习笔记-数据管理系统设计实现
QT学习笔记-数据管理系统设计实现
2022-07-29 05:22:00 【Q-Stark】
前言
因工作需要,要实现一个小型的数据管理系统。本着想捡起来QT技能的想法,学习下QT下管理系统设计。
一、功能需求
首先肯定是设计界面按照想要的方式进行展示,使用sqlite对数据进行管理,数据excel格式的导入导出,界面的搜索功能,条件选择功能,单条数据的编辑更改功能,账户管理功能。
二、功能设计
根据不同模块进行分类设计
数据仓库类
对于数据源的管理设计DBFactory类对数据库操作进行封装,提供数据库连接,创建表,select等操作
数据模型类
模型本身不存储数据,仅提供接口供视图使用,QT提供的QsqlTableModel已经够用
单条数据的编辑可用QDataWidgetMaper类进行数据映射。
数据视图类
提供视图用来展示数据,和搜索功能
数据I/O类
提供excel文件的导入导出功能
登录管理类
提供登录功能及账户管理功能
三、具体实现
1.仓库类
定义了创建数据库连接和创建表的函数。
#ifndef DBFACTORY_H
#define DBFACTORY_H
#include <QtSql>
#include <QSqlDatabase>
class DBFactory
{
public:
DBFactory();
QSqlError createConnection();
QSqlError createUserTable(const QSqlDatabase &DataBase);
QSqlError createTable(const QSqlDatabase &DataBase);
void addUser(QSqlQuery &q, const QString &name, const QString &password,const QString &phoneNumber,const QString &role);
void addProvince(QSqlQuery &q, const QString &province, const QString &area);
QSqlDatabase DataBase() const;
void setDataBase(const QSqlDatabase &DataBase);
QStringList getContentFromDataBase(const QString &tableName, const int column);
private:
QSqlDatabase m_DataBase;
};
#endif // DBFACTORY_H
具体实现可以参考QT帮助文档关于SQL的页面。
2.登录管理类
提供一个对话框供用户输入用户名和密码。
在main函数中,首先构造登录对话框,在登录对话框构造函数中,建立数据库连接,并初始化用户表,如有,则直接跳过。
LoginDialog::LoginDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::LoginDialog)
{
//建立数据库连接
m_pDBFactory = new DBFactory();
QSqlError err = m_pDBFactory->createConnection();
if(err.type() != QSqlError::NoError)
{
QMessageBox::critical(this,tr("错误"),tr("数据库连接错误,请稍后重试!")+ err.text(),QMessageBox::Ok);
// return;
}
m_pDBFactory->createUserTable(m_pDBFactory->DataBase());
ui->setupUi(this);
}
用户输入完成后点击界面登录按钮触发相应槽函数,在对应槽函数中,检索数据库用户表,匹配密码是否正确。如正确则发出accept信号,主函数接受到后,关闭登录界面,打开主显示界面。
if(checkUserPassword(ui->UserNameEdit->text(),ui->PassWordEdit->text()))
{
QDialog::accept();}
bool LoginDialog::checkUserPassword(QString name,QString passward)
{
QSqlQuery checkquery;
QString str = QString("select * from user where UName = '%1' and UPassward = '%2'").arg(name).arg(passward);
checkquery.exec(str);
//返回最后一条符合记录的位置,
checkquery.last();
int record = checkquery.at() + 1;
if(record == 0)
{
return false;
}
loginRole = checkquery.value(3).toString();
qDebug()<<loginRole;
return true;
}
在checkuserPassword函数中检索数据库,并根据不同的用户名分配不同的权限,传递给主界面构造函数用于限制部分功能。
3.主界面类
主界面用于管理视图和模型,提供一个构造函数,和相应的菜单及其槽函数。在构造函数中进行相应视图的创建。并根据传入角色分配不同的菜单。
MainWindow::MainWindow(const QString &role, QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建数据表格,导入数据
m_pDBFactory = new DBFactory();
m_pDBFactory->createCustomerTable(m_pDBFactory->DataBase());
//先构建视图
m_pViewManager = new ViewManager();
setCentralWidget(m_pViewManager->pTabWidget());
//获取视图对应的模型
m_pModel=m_pViewManager->pCustomerManager()->getCustomerModel();
CreateMenu(role);
}
4.视图管理类
为方便拓展,先建立一个视图管理类添加一个tabwidget控件,再结合不同模型建立对应视图类,将视图作为tab页添加到视图管理类的tab控件中。
自定义视图
使用QTableView控件作为视图进行数据展示。使用该控件提供的函数进行一些基本的增删改查函数编写。
默认该视图是可编辑的,故提供了一个函数用来导入模型并设置标签。并在视图构造函数中调用并将模型设置给视图。
bool CustomerManager::setModel()
{
//关联数据模型
customerModel = new QSqlTableModel(ui->tableView);
customerModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
customerModel->setTable("Customers");
//添加表头
customerModel->setHeaderData(0,Qt::Horizontal, tr("ID"));
customerModel->setHeaderData(1,Qt::Horizontal, tr("客户地址"));
// Populate the model:
if(!customerModel->select())
{
return false;
}
return true;
}
setModel();
ui->tableView->setModel(customerModel);
//列宽随窗口大小改变而改变,每列平均分配,充满整个表,但是此时列宽不能拖动进行改变
ui->tableView->resizeColumnsToContents();
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableView->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
上边的步骤完成后,就可以将数据库中的数据显示在界面上了。接下来就是实现增删改查的功能。
单行新增
通过按钮槽函数,打开新的对话框表单,填写后将表单获取的数据组合成需要的SQL语句并提交,在槽函数中更新视图。
void CustomerManager::on_addButton_clicked()
{
AddCustomerDialog *dialog = new AddCustomerDialog(customerModel,this);
int accepted = dialog->exec();
if (accepted == 1)
{
int lastRow = customerModel->rowCount() - 1;
ui->tableView->selectRow(lastRow);
ui->tableView->scrollToBottom();
}
}
单行删除
删除选中记录,因视图设置为单行选中,所以仅实现单行删除功能。
void CustomerManager::delCustomer()
{
QModelIndexList selection = ui->tableView->selectionModel()->selectedRows(0);
if(!selection.empty())
{
QModelIndex idIndex = selection.at(0);
QMessageBox::StandardButton button;
button = QMessageBox::question(this,tr("删除确认"),QString(tr("确认删除此条客户信息吗?")),QMessageBox::Yes|QMessageBox::No);
if(button == QMessageBox::Yes){
removeCustomerFromDatabase(idIndex);
}else{
QMessageBox::information(this, tr("删除客户"),tr("请选择要删除的客户信息。"));
}
}
}
void CustomerManager::removeCustomerFromDatabase(QModelIndex index)
{
customerModel->removeRow(index.row());
customerModel->submit();
}
条件搜索
条件选择搜索功能实现,依据下拉框选项组合where条件选择语句,设置customermodel的过滤器filter。
如
void CustomerManager::on_AreaSelectBox_currentIndexChanged(const QString &arg1)
{
//更新省区选择项
QSqlQueryModel *provinceselectModel = new QSqlQueryModel(this);
QString provinceSelectstr = QString("select DISTINCT province from Provinces where area = '%1'").arg(arg1);
provinceselectModel->setQuery(provinceSelectstr);
ui->ProvinceSelectBox->setModel(provinceselectModel);
if(arg1 != "请选择归属大区"){
//构建过滤器即where条件语句
QString filter;
filter.append(QString("CArea = '%1'").arg(arg1));
if(ui->ProvinceSelectBox->currentText()!= "请选择归属省份")
{
filter.append(QString(" and "));
filter.append(QString("CProvince = '%1'").arg(ui->ProvinceSelectBox->currentText()));
}
if(ui->ProduceTypeBox->currentText()!="请选择企业性质")
{
filter.append(QString(" and "));
filter.append(QString("CProduceType = '%1'").arg(ui->ProduceTypeBox->currentText()));
}
if(ui->CustomerTypeBox->currentText()!="请选择客户类型")
{
filter.append(QString(" and "));
filter.append(QString("CCustomerType = '%1'").arg(ui->CustomerTypeBox->currentText()));
}
qDebug()<<filter;
customerModel->setFilter(filter);
ui->ProvinceSelectBox->setEnabled(true);
}else
{
//重置所有下拉框并显示所有数据
ui->ProvinceSelectBox->setCurrentIndex(0);
ui->ProvinceSelectBox->setEnabled(false);
ui->ProduceTypeBox->setCurrentIndex(0);
ui->CustomerTypeBox->setCurrentIndex(0);
customerModel->setFilter(QString(""));
customerModel->select();
}
}
文字搜索
文字搜索功能实现,依据输入文本对视图数据项进行检索
void CustomerManager::on_SearchButton_clicked()
{
QString searchText = ui->SearchEdit->text();
if(searchText=="")
{
for(int i=0;i<ui->tableView->model()->rowCount();i++)
ui->tableView->setRowHidden(i,false);
}
else
{
//获取文本框内容
searchText.remove(QRegExp("\\s"));
for(int i=0;i<ui->tableView->model()->rowCount();i++)
{
ui->tableView->setRowHidden(i,true);
QString r="";
//提取客户信息
QAbstractItemModel *model=ui->tableView->model();
QModelIndex index;
for(int j=0;j<ui->tableView->model()->columnCount();j++)
{
index=model->index(i,j);
r+=model->data(index).toString();
}
r.remove(QRegExp("\\s"));
if(r.contains(searchText,Qt::CaseSensitive))
ui->tableView->setRowHidden(i,false);
}
}
}
后记
后期还需实现图片显示,数据量大时分页显示,可通过子类化QSQLTableModel来实现。
边栏推荐
- C connect to SharePoint online webservice
- HR面必问问题——如何与HR斗志斗勇(收集于FPGA探索者)
- Migration learning - geodesic flow kernel for unsupervised domain adaptation
- 五、图像像素统计
- 【Attention】Visual Attention Network
- 一、multiprocessing.pool.RemoteTraceback
- ML16-神经网络(2)
- Beijing Baode & taocloud jointly build the road of information innovation
- 电脑视频暂停再继续,声音突然变大
- NLP领域的AM模型
猜你喜欢
ROS常用指令
ROS教程(Xavier)
预训练语言模型的使用方法
iSCSI vs iSER vs NVMe-TCP vs NVMe-RDMA
研究生新生培训第三周:ResNet+ResNeXt
1、 Focal loss theory and code implementation
Migration learning - geodesic flow kernel for unsupervised domain adaptation
ML16 neural network (2)
PyTorch的数据读取机制
虚假新闻检测论文阅读(二):Semi-Supervised Learning and Graph Neural Networks for Fake News Detection
随机推荐
Configuration and use of Nacos external database
虚假新闻检测论文阅读(一):Fake News Detection using Semi-Supervised Graph Convolutional Network
ML15 neural network (1)
[image classification] how to use mmclassification to train your classification model
Error in installing pyspider under Windows: Please specify --curl dir=/path/to/build/libcurl solution
Discussion on the design of distributed full flash memory automatic test platform
一、迁移学习与fine-tuning有什么区别?
2、 Multi concurrent interface pressure test
Briefly talk about the difference between pendingintent and intent
ML16-神经网络(2)
四、One-hot和损失函数的应用
六、基于深度学习关键点的指针式表计识别
迁移学习—Geodesic Flow Kernel for Unsupervised Domain Adaptation
iSCSI vs iSER vs NVMe-TCP vs NVMe-RDMA
Is flutter being quietly abandoned? On the future of flutter
京微齐力:基于HMEP060的OLED字符显示(及FUXI工程建立演示)
[semantic segmentation] overview of semantic segmentation
基于FPGA:多目标运动检测(手把手教学①)
2、 How to save the images of train and test in MNIST dataset?
引入Spacy模块出错—OSError: [E941] Can‘t find model ‘en‘.