1. 程式人生 > >Qt5 學習參考資料之--QSqlTableModel

Qt5 學習參考資料之--QSqlTableModel

源部落格地址:http://www.qter.org/portal.php?mod=view&aid=57

 

導語


       在上一篇我們講到只讀的QSqlQueryModel模型其實也可以實現編輯功能的,但是實現起來很麻煩。而QSqlTableModel提供了一個一次只能操作單個SQL表的讀寫模型,它是QSqlQuery的更高層次的替代品,可以瀏覽和修改獨立的SQL表,並且只需編寫很少的程式碼,而且不需要了解SQL語法。


 

環境:Windows 7 + Qt 5.8.0(包含QtCreator 4.2.1

 

 

正文


 

一、建立資料庫

 

 

1.新建Qt Widgets應用,專案名稱為tablemodel,基類為QMainWindow,類名MainWindow。

 

2.完成後開啟tablemodel.pro檔案,將第一行程式碼更改為:

  1. QT       += coregui sql

複製程式碼

       然後儲存檔案。

 

 

3.向專案中新增新的C++標頭檔案,名稱為connection.h。完成後將其內容更改如下:

  1. #ifndef CONNECTION_H
  2. #define CONNECTION_H
  3.  
  4. #include <QSqlDatabase>
  5. #include <QSqlQuery>
  6.  
  7. static bool createConnection()
  8. {
  9.     QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
  10.     db.setDatabaseName("database.db");
  11.     if(!db.open()) return false;
  12.     QSqlQuery query;
  13.     query.exec("create table student (id int primary key, name vchar)");
  14.     query.exec("insert into student values (0,'劉明')");
  15.     query.exec("insert into student values (1,'陳剛')");
  16.     query.exec("insert into student values (2,'王紅')");
  17.     return true;
  18. }
  19.  
  20. #endif // CONNECTION_H

複製程式碼


 

4.下面將main.cpp檔案更改如下:

 

  1. #include "mainwindow.h"
  2. #include <QApplication>
  3. #include "connection.h"
  4.  
  5. int main(int argc, char *argv[])
  6. {
  7.     QApplication a(argc, argv);
  8.  
  9.     if(!createConnection())
  10.         return 1;
  11.  
  12.     MainWindow w;
  13.     w.show();
  14.  
  15.     return a.exec();
  16. }

複製程式碼


 

5.下面進入設計模式,向視窗上拖入Label、Push Button、Line Edit和Table View等部件,進行介面設計,效果如下圖所示。

 

 

01.png

 

6.完成後到mainwindow.h檔案中,先包含標頭檔案:

  1. #include <QSqlTableModel>

複製程式碼

 

然後新增私有物件:

  1. QSqlTableModel *model;

複製程式碼

 

7.到mainwindow.cpp,在建構函式新增如下程式碼:

  1. model = new QSqlTableModel(this);
  2. model->setTable("student");
  3. model->setEditStrategy(QSqlTableModel::OnManualSubmit);
  4. model->select(); //選取整個表的所有行
  5.  
  6. //不顯示name屬性列,如果這時新增記錄,則該屬性的值新增不上
  7. // model->removeColumn(1);
  8.  
  9. ui->tableView->setModel(model);
  10.  
  11. //使其不可編輯
  12. // ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);

複製程式碼

 

這裡建立一個QSqlTableModel後,只需使用setTable()來為其指定資料表,然後使用select()函式進行查詢,呼叫這兩個函式就等價於執行了“select * from student”這個SQL語句。這裡還可以使用setFilter()來指定查詢時的條件,在後面會看到這個函式的使用。在使用該模型以前,一般還要設定其編輯策略,它由QSqlTableModel::EditStrategy列舉型別定義,一共有三個值,如下圖所示。用來說明當資料庫中的值被編輯後,什麼情況下提交修改。

 

02.jpg

 

執行程式,效果如下圖所示。

 

 

03.png


 

       可以看到,這個模型已經完全脫離了SQL語句,我們只需要執行select()函式就能查詢整張表。上面有兩行程式碼被註釋掉了,你可以取消註釋,測試一下它們的作用。

 

 

二、修改操作

 

 

1.我們進入“提交修改”按鈕的單擊訊號槽,更改如下:

  1. void MainWindow::on_pushButton_clicked()
  2. {
  3.     model->database().transaction(); //開始事務操作
  4.     if (model->submitAll()) {
  5.         model->database().commit(); //提交
  6.     } else {
  7.         model->database().rollback(); //回滾
  8.         QMessageBox::warning(this, tr("tableModel"),
  9.                              tr("資料庫錯誤: %1")
  10.                              .arg(model->lastError().text()));
  11.     }
  12. }

複製程式碼


 

       這裡用到了事務操作,真正起提交操作的是model->submitAll()一句,它提交所有更改。

 

2.進入“撤銷修改”按鈕的單擊訊號槽,更改如下:

  1. void MainWindow::on_pushButton_2_clicked()
  2. {
  3.     model->revertAll();
  4. }

複製程式碼

 

3.在mainwindow.cpp檔案中包含標頭檔案:

  1. #include <QMessageBox>
  2. #include <QSqlError>

複製程式碼


 

4.現在執行程式,我們將“陳剛”改為“李強”,如果我們點選“撤銷修改”,那麼它就會重新改為“陳剛”,而當我們點選“提交修改”後它就會儲存到資料庫,此時再點選“撤銷修改”就修改不回來了。

       可以看到,這個模型可以將所有修改先儲存到model中,只有當我們執行提交修改後,才會真正寫入資料庫。當然這也是因為我們在最開始設定了它的儲存策略:

  1. model->setEditStrategy(QSqlTableModel::OnManualSubmit);

複製程式碼

 

這裡的OnManualSubmit表明我們要提交修改才能使其生效。


 

三、查詢操作

 

 

1.進入“查詢”按鈕的單擊訊號槽,更改如下:

 

  1. void MainWindow::on_pushButton_5_clicked()
  2. {
  3.     QString name = ui->lineEdit->text();
  4.     //根據姓名進行篩選
  5.     model->setFilter(QString("name = '%1'").arg(name));
  6.     //顯示結果
  7.     model->select();
  8. }

複製程式碼


 

       使用setFilter()函式進行關鍵字篩選,這個函式是對整個結果集進行查詢。

 

 

2.進入“顯示全表”按鈕的單擊訊號槽,更改如下:

 

  1. void MainWindow::on_pushButton_6_clicked()
  2. {
  3.     model->setTable("student");   //重新關聯表
  4.     model->select();   //這樣才能再次顯示整個表的內容
  5. }

複製程式碼

 

為了再次顯示整個表的內容,我們需要再次關聯這個表。


 

3.下面執行程式,輸入一個姓名,點選“查詢”按鈕後,就可以顯示該記錄了。再點選“顯示全表”按鈕則返回。如下圖所示。

 

 

04.png


 

四、排序操作

 

 

分別進入“按id升序排序”和“按id降序排序”按鈕的單擊訊號槽,更改如下:

 

  1. // 升序
  2. void MainWindow::on_pushButton_7_clicked()
  3. {
  4.     //id屬性即第0列,升序排列
  5.     model->setSort(0, Qt::AscendingOrder);
  6.     model->select();
  7. }
  8. // 降序
  9. void MainWindow::on_pushButton_8_clicked()
  10. {
  11.     model->setSort(0, Qt::DescendingOrder);
  12.     model->select();
  13. }

複製程式碼


 

這裡使用了setSort()函式進行排序,它有兩個引數,第一個引數表示按第幾個欄位排序,表頭從左向右,最左邊是第0個欄位,這裡就是id欄位。第二個引數是排序方法,有升序和降序兩種。執行程式,效果如下圖所示。


 

05.png



 

五、刪除操作

 

 

我們進入“刪除選中行”按鈕的單擊訊號槽,更改如下:

 

  1. void MainWindow::on_pushButton_4_clicked()
  2. {
  3.     //獲取選中的行
  4.     int curRow = ui->tableView->currentIndex().row();
  5.  
  6.     //刪除該行
  7.     model->removeRow(curRow);
  8.  
  9.     int ok = QMessageBox::warning(this,tr("刪除當前行!"),
  10.                                   tr("你確定刪除當前行嗎?"),
  11.                                   QMessageBox::Yes,QMessageBox::No);
  12.     if(ok == QMessageBox::No)
  13.     {
  14.         model->revertAll(); //如果不刪除,則撤銷
  15.     }
  16.     else model->submitAll(); //否則提交,在資料庫中刪除該行
  17. }

複製程式碼

 

刪除行的操作會先儲存在model中,當我們執行了submitAll()函式後才會真正的在資料庫中刪除該行。這裡我們使用了一個警告框來讓使用者選擇是否真得要刪除該行。執行程式,效果如下圖所示。


 

06.png


 

我們單擊第二行,然後單擊“刪除選中行”按鈕,出現了警告框。這時你會發現,表中的第二行前面出現了一個小感嘆號,表明該行已經被修改了,但是還沒有真正在資料庫中修改,這時的資料有個學名叫髒資料(Dirty Data)。當我們按鈕“Yes”按鈕後資料庫中的資料就會被刪除,如果按下“No”,那麼更改就會取消。


 

六、插入操作

 

 

       我們進入“新增記錄”按鈕的單擊訊號槽,更改如下:

 

  1. void MainWindow::on_pushButton_3_clicked()
  2. {
  3.     int rowNum = model->rowCount(); //獲得表的行數
  4.     int id = 10;
  5.     model->insertRow(rowNum); //新增一行
  6.     model->setData(model->index(rowNum,0),id);
  7.     //model->submitAll(); //可以直接提交
  8. }

複製程式碼

 

在表的最後新增一行,因為在student表中我們設定了id號是主鍵,所以這裡必須使用setData()函式給新加的行新增id欄位的值,不然新增行就不會成功。這裡可以直接呼叫submitAll()函式進行提交,也可以利用“提交修改”按鈕進行提交。執行程式,效果如下圖所示。


 

07.png


 

按下“新增記錄”按鈕後,就添加了一行,不過在該行的前面有個星號,如果我們按下“提交修改”按鈕,這個星號就會消失。當然,如果我們將上面程式碼裡的提交函式的註釋去掉,也就不會有這個星號了。


 

結語


 

可以看到這個模型很強大,而且完全脫離了SQL語句,就算你不怎麼懂資料庫知識,也可以利用它進行大部分常用的操作。我們也看到了,這個模型提供了緩衝區,可以先將修改儲存起來,當我們執行提交函式時,再去真正地修改資料庫。當然,這個模型比前面的模型更高階,前面講的所有操作,在這裡都能執行。