Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作

本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78615800

 

 

Qt实用技巧:使用QTableView、QSqlTableMode与QSqlDatabase对数据库数据进行操作

需求

 

        编写应用软件的过程中,需要对保存的数据进行动态的设置,当程序运行的时查询数据库获取相关配置项进行设置。

 

原理

 

        使用时,将QSqlTableModel与QSqlDatabase绑定即model与sql绑定,然后将model与QTableView绑定,实现修改QTableView时,自动更新对数据库的操作,基本的数据库操作语句都省了。

 

Demo

Demo下载地址:http://download.csdn.net/download/qq21497936/10130238

 

Demo包含

Demo截图

 

关键代码

对于数据库的操作:打开数据库

[cpp] view plain copy
 
  1.     _db = QSqlDatabase::addDatabase("QSQLITE");  
  2.     _db.setDatabaseName("demo.db");  
  3.   
  4.     // 数据库文件是否在应用程序目录下,因为在编码时,应用程序默认路径在.pro文件夹下,但是实际exe路径在的其debug或者release文件夹下  
  5.     // 补充:不论linux还是windows,统一使用单斜杠作为分隔,在linux和windows下都能识别,能更好的跨平台  
  6. #if 0  
  7.     // 发布时  
  8.     QString path = qApp->applicationDirPath()+"/"+"demo.db";  
  9. #else  
  10.     // 编译时  
  11.     QString path = qApp->applicationDirPath()+"/../"+"demo.db";  
  12. #endif  
  13.     if(QFile::exists(path))  
  14.   
  15.     {  
  16.         // 存在则打开  
  17.         _db.open();  
  18.     }else{  
  19.         // 不存在打开并创建数据库表 补充:SQLite是基于文件的数据库,当打开时如果数据库文件不存在将自动创建一个  
  20.         _db.open();  
  21.         QSqlQuery query;  
  22.         // set为sqlite关键字,不能使用  
  23.         bool bRet = query.exec("create table init(" \  
  24.                                "no   INT    PRIMARY KEY NOT NULL,"\  
  25.                                "name TEXT   NOT NULL,"\  
  26.                                "content TEXT,"\  
  27.                                "description TEXT"\  
  28.                                ");");  
  29.         if(!bRet) {  
  30.             _db.close();  
  31.             QFile::remove(path);  
  32.         }else{  
  33.             // 此处演示了三种不同insert插入方法  
  34.             query.exec("insert into init values" \  
  35.                        "(1, '启动界面背景', 'images/background.jpg', '请使用1920*1080的图片,图片格式可以为png、jpg。');");  
  36.             query.exec("insert into init       " \  
  37.                        "(no,name,content,description) values(2, '欢迎视频', '','进入启动界面后,循环播放的视频,必须为mp4格式,如果为空则循环播放欢迎音乐');");  
  38.             query.exec("insert into init       " \  
  39.                        "(no,name,description) values (3, '欢迎音乐','进去启动界面后,循环播放的音频文件,可选择mp3,wav格式');");  
  40.         }  
  41.     }  

 

QSqlTableMode与数据库绑定

[cpp] view plain copy
 
  1. // 如果使用MySqlTableModel,重写了data,但是导致直接点击数据修改的时候,没有更新TableView,不知原因  
  2. // 如果使用QSqlTableMode,则无法通过重载实现每一行自动居中等一些单元格的统一操作,只能遍历单元格设置  
  3. QSqlTableModel *pModel = new QSqlTableModel(this, _db);  
  4. pModel->setTable("init");  
  5. // 三种提交方式,改动即提交,选择其他行时提交,手动提交;经实际测试,其中只有手动提交在显示效果上是最好的  
  6. pModel->setEditStrategy(QSqlTableModel::OnManualSubmit);  
  7. pModel->select();  
  8. pModel->setHeaderData(0, Qt::Horizontal, "序号");  
  9. pModel->setHeaderData(1, Qt::Horizontal, "名称");  
  10. pModel->setHeaderData(2, Qt::Horizontal, "内容");  
  11. pModel->setHeaderData(3, Qt::Horizontal, "描述");  
  12. pModel->sort(0, Qt::AscendingOrder); // 第0列升序排序  

QTableView与QSqlTableMode绑定

 

[cpp] view plain copy
 
  1. ui->tableView->setModel(pModel);  

 

QTableView的初始化设置

[cpp] view plain copy
 
  1. // grid原本就是有多少格显示多少格,  
  2.   ui->tableView->setShowGrid(false); // 可隐藏grid  
  3. // 只能单选  
  4. ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);  
  5. // 以行作为选择标准  
  6. ui->tableView->setSelectionBehavior(QAbstractItemView::QAbstractItemView::SelectRows);  
  7. // 行头隐藏  
  8. ui->tableView->verticalHeader()->hide();  
  9. // 让列头可被点击,触发点击事件  
  10. ui->tableView->horizontalHeader()->setSectionsClickable(true);  
  11. // 去掉选中表格时,列头的文字高亮  
  12. ui->tableView->horizontalHeader()->setHighlightSections(false);  
  13. ui->tableView->horizontalHeader()->setBackgroundRole(QPalette::Background);  
  14. // 列头灰色  
  15. ui->tableView->horizontalHeader()->setStyleSheet("QHeaderView::section{background-color:rgb(225,225,225)};");  
  16. connect(ui->tableView->horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(sortByColumn(int)));  

QTableView点击列头的排序操作(初始化时,开启了列头clicked和关联信号槽)

 

[cpp] view plain copy
 
  1. void MainWindow::sortByColumn(int col)  
  2. {  
  3.     QSqlTableModel *pMode = dynamic_cast<QSqlTableModel *>(ui->tableView->model());  
  4.     bool ascending = (ui->tableView->horizontalHeader()->sortIndicatorSection()==col  
  5.                       && ui->tableView->horizontalHeader()->sortIndicatorOrder()==Qt::DescendingOrder);  
  6.     Qt::SortOrder order = ascending ? Qt::AscendingOrder : Qt::DescendingOrder;  
  7.     pMode->sort(col, order);  
  8. }  

 

QTableView修改一行的保存操作

[cpp] view plain copy
 
  1. void MainWindow::on_pushButton_save_clicked()  
  2. {  
  3.   
  4.     QSqlTableModel *pMode = dynamic_cast<QSqlTableModel *>(ui->tableView->model());  
  5.     pMode->database().transaction(); //开始事务操作  
  6.     if (pMode->submitAll()) // 提交所有被修改的数据到数据库中  
  7.     {  
  8.         pMode->database().commit(); //提交成功,事务将真正修改数据库数据  
  9.     } else {  
  10.         pMode->database().rollback(); //提交失败,事务回滚  
  11.         QMessageBox::warning(this, tr("tableModel"),tr("数据库错误: %1").arg(pMode->lastError().text()));  
  12.     }  
  13.     pMode->revertAll(); //撤销修改  
  14. }  

QTableView新增一行的操作

[cpp] view plain copy
 
  1. void MainWindow::on_pushButton_add_clicked()  
  2. {  
  3.     QSqlTableModel *pMode = dynamic_cast<QSqlTableModel *>(ui->tableView->model());  
  4. //    pMode->insertRow(pMode->rowCount());  
  5.     QSqlRecord record = pMode->record();  
  6.     int number;  
  7.     // 从1开始遍历,遇到相同的,自增再遍历,直到没有相同的作为number插入  
  8.     // 防止唯一主键重复导致提交失败,因为提交失败tableview还是会更新修改后的(视图)  
  9.     for(number = 1; ; number++)  
  10.     {  
  11.         bool bFlag = false;  
  12.         for(int index = 0; index < pMode->rowCount(); index++) {  
  13.             if(pMode->index(index, 0).data().toInt() == number) {  
  14.                 bFlag = true;  
  15.                 break;  
  16.             }  
  17.         }  
  18.         if(!bFlag) {  
  19.             break;  
  20.         }  
  21.     }  
  22.     record.setValue(0, number);  
  23.     record.setValue(1, "未命令");  
  24.     record.setValue(2, "空");  
  25.     record.setValue(3, "空");  
  26.     pMode->insertRecord(pMode->rowCount(), record);  
  27.     // 每次手动提交,都会重新刷新tableView,保持mode和tableView一致  
  28.     pMode->submitAll();  
  29. }  

QTableView删除一行的操作

 

[cpp] view plain copy
 
  1. void MainWindow::on_pushButton_del_clicked()  
  2. {  
  3.     QSqlTableModel *pMode = dynamic_cast<QSqlTableModel *>(ui->tableView->model());  
  4.     // 当QSqlTableModel::EditStrategy 选择 非QSqlTableModel::OnManualSubmit 时,  
  5.     // 每次删除都可删除掉model,但是tableview那一列为空,一直在,只好设置为 QSqlTableModel::OnManualSubmit  
  6.     pMode->removeRow(ui->tableView->currentIndex().row());  
  7.     // 每次手动提交,都会重新刷新tableView,保持mode和tableView一致  
  8.     pMode->submitAll();  
  9. }  

 

拓展

        整个应用,可只打开一次QSqlDatabase,程序中第一次使用了QDatabase,打开后不关闭且不再打开新的数据库,其他类中可直接声明QSqlDatabase对象db,然后使用QSqlQuery进行查询操作。(正常以为是需要传递,但Qt机制中,此处可不第二次打开,只要第一次不关闭,但是都必须在一个应用中)。

 

http://blog.csdn.net/qq21497936/article/details/78615800

posted @ 2018-01-05 17:45  findumars  Views(3867)  Comments(0Edit  收藏  举报