自学内容网 自学内容网

QT数据库(二):QSqlQueryModel实现数据查询

QSqlQueryModel 可以设置任意的 SELECT 语句来从数据库中查询数据,可以查询一个数据表部分字段的数据,也可以是多个数据表组合的数据。该模型的数据是只读的,即使在界面上修改了QSqlQueryModel 模型的数据,也不能将所做的修改提交到数据库。

要从数据库查询数据并将其作为 QSqlQueryModel 的数据源,需要运行函数 setQuery()

有两种原型:

void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase())

参数 query 是一条完整的 SELECT 查询语句;参数 db 是数据库连接,若不指定数据库连接, 就用程序默认的数据库连接。

void QSqlQueryModel::setQuery(QSqlQuery &&query)

QSqlQuery 是可以运行任何 SQL 语句的类,当然也能运行 SELECT 语句从数据库获取数据。

查询出数据后,可以用 QSqlQueryModel 的函数 record()访问数据记录。

//1. 创建数据模型,查询数据
    qryModel=new QSqlQueryModel(this);
    qryModel->setQuery("SELECT empNo, Name, Gender,  Birthday,  Province,  Department, "
                       " Salary FROM employee ORDER BY empNo",DB);
    if (qryModel->lastError().isValid())
    {
        QMessageBox::critical(this, "错误", "数据表查询错误,错误信息\n"
                              +qryModel->lastError().text());
        return;
    }

  //2. 设置字段显示标题
    QSqlRecord rec=qryModel->record();  //获取一个空记录,为了获取字段序号
    qryModel->setHeaderData(rec.indexOf("empNo"),  Qt::Horizontal, "工号");
    qryModel->setHeaderData(rec.indexOf("Name"),   Qt::Horizontal, "姓名");
    qryModel->setHeaderData(rec.indexOf("Gender"), Qt::Horizontal, "性别");
    qryModel->setHeaderData(rec.indexOf("Birthday"),   Qt::Horizontal, "出生日期");
    qryModel->setHeaderData(rec.indexOf("Province"),   Qt::Horizontal, "省份");
    qryModel->setHeaderData(rec.indexOf("Department"), Qt::Horizontal, "部门");
    qryModel->setHeaderData(rec.indexOf("Salary"),     Qt::Horizontal, "工资");

  //3. 创建选择模型
    selModel=new QItemSelectionModel(qryModel,this);
    connect(selModel,&QItemSelectionModel::currentRowChanged,this, &MainWindow::do_currentRowChanged);
    ui->tableView->setModel(qryModel);
 //4. 创建数据映射
    dataMapper= new QDataWidgetMapper(this);
    dataMapper->setSubmitPolicy(QDataWidgetMapper::AutoSubmit);
    dataMapper->setModel(qryModel);

    //界面组件与数据模型的具体字段之间的映射
    dataMapper->addMapping(ui->dbSpinEmpNo, rec.indexOf("empNo"));
    dataMapper->addMapping(ui->dbEditName,  rec.indexOf("Name"));
    dataMapper->addMapping(ui->dbComboSex,  rec.indexOf("Gender"));
    dataMapper->addMapping(ui->dbEditBirth, rec.indexOf("Birthday"));
    dataMapper->addMapping(ui->dbComboProvince, rec.indexOf("Province"));
    dataMapper->addMapping(ui->dbComboDep,      rec.indexOf("Department"));
    dataMapper->addMapping(ui->dbSpinSalary,    rec.indexOf("Salary"));

    dataMapper->toFirst();  //移动到首记录

record函数不带参数可以获取字段名称,想要获取对应记录的字段对应值,可以参考以下:

    QSqlRecord rec1=qryModel->record(2);
    QVariant vr = rec1.value("Name");
    QString qs = vr.toString();
    qDebug() << qs;

使用ui->tableView->setSelectionModel(selModel);语句将界面显示与模型绑定在一起。

dataMapper将UI中的一系列界面组件映射到一条记录的不同字段,便设置显示为第一条记录的数据内容。

ui->tableView->setSelectionModel(selModel);设置了选择模型,当选择的行发生改变时候会进入以下槽函数:

void MainWindow::do_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{
    Q_UNUSED(previous);
    if (!current.isValid())
    {
        ui->dbLabPhoto->clear();
        ui->dbEditMemo->clear();
        return;
    }

    dataMapper->setCurrentModelIndex(current);      //设置当前行
    //    dataMapper->setCurrentIndex(current.row());   //这个也可以

    bool first=(current.row()==0);  //是否首记录
    bool last=(current.row()==qryModel->rowCount()-1);  //是否尾记录

    ui->actRecFirst->setEnabled(!first);    //更新使能状态
    ui->actRecPrevious->setEnabled(!first);
    ui->actRecNext->setEnabled(!last);
    ui->actRecLast->setEnabled(!last);

    int curRecNo=selModel->currentIndex().row();
    QSqlRecord  curRec=qryModel->record(curRecNo);  //获取当前记录
    int empNo=curRec.value("EmpNo").toInt();    //主键字段

    QSqlQuery query(DB);    //查询某个empNo的Memo和Photo字段的数据
    query.prepare("select EmpNo, Memo, Photo from employee where EmpNo = :ID");
    query.bindValue(":ID",empNo);
    query.exec();
    query.first();

    QVariant    va=query.value("Photo");
    if (!va.isValid())  //图片字段内容为空
        ui->dbLabPhoto->clear();
    else    //显示图片
    {
        QByteArray data=va.toByteArray();
        QPixmap pic;
        pic.loadFromData(data);
        ui->dbLabPhoto->setPixmap(pic.scaledToWidth(ui->dbLabPhoto->size().width()));
    }

    QVariant    va2=query.value("Memo");    //显示备注
    ui->dbEditMemo->setPlainText(va2.toString());
}

在槽函数中获取当前选择的记录,并设置dataMapper,选择的记录条在其他组件中同步更新,获取该记录的一些数据,然后用一个 QSqlQuery 变量 query 运行查询语句,查询对应EmpNo号对应记录的BLOB类型数据,并转化显示为图片。

记录的移动需要根据 QDataWidgetMapper 对象的当前行设置选择模型的当前行,这样才能使

QTableView组件和数据感知组件的当前行是同步的。


void MainWindow::on_actRecFirst_triggered()
{ //首记录
    dataMapper->toFirst();
    refreshTableView();
}

void MainWindow::on_actRecPrevious_triggered()
{ //前一记录
    dataMapper->toPrevious();
    refreshTableView();
}

void MainWindow::on_actRecNext_triggered()
{//后一记录
    dataMapper->toNext();
    refreshTableView();
}

void MainWindow::on_actRecLast_triggered()
{//尾记录
    dataMapper->toLast();
    refreshTableView();
}

//刷新tableView的当前行
void MainWindow::refreshTableView()
{
    int index=dataMapper->currentIndex();   //dataMapper的当前行号
    QModelIndex curIndex=qryModel->index(index,1);  //为当前行创建模型索引
    selModel->clearSelection();         //清空选择项
    selModel->setCurrentIndex(curIndex,QItemSelectionModel::Select);    //设置当前行
}


原文地址:https://blog.csdn.net/qq_46144191/article/details/144360245

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!