QT学习笔记-数据管理系统设计实现


前言

因工作需要,要实现一个小型的数据管理系统。本着想捡起来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来实现。

  • 6
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值