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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM