Qt資料庫(六)QSqlTableModel

來源:互聯網
上載者:User

本文章原創於www.yafeilinux.com 轉載請註明出處。

在上一篇我們講到唯讀QSqlQueryModel也可以使其可編輯,但是很麻煩。Qt提供了操作單表的QSqlTableModel,如果我們需要對錶的內容進行修改,那麼我們就可以直接使用這個類。

QSqlTableModel,該類提供了一個可讀寫單張SQL表的可編輯資料模型。我們下面就對其的幾個常用功能進行介紹,分別是修改,插入,刪除,查詢,和排序。

在開始講之前,我們還是建立Qt4 Gui Application工程,我這裡工程名為tableModel ,然後選中QtSql模組,Base class選QWidget。工程建好後,添加C++ Header File ,命名為database.h,更改其內容如下:

#ifndef DATABASE_H
#define DATABASE_H

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QObject>
static bool createConnection()
{
    QSqlDatabase db = QSqlDatabase::addDatabase(“QSQLITE”);
    db.setDatabaseName(“database.db”);
    if(!db.open()) return false;
    QSqlQuery query;
    query.exec(QObject::tr(“create table student (id int primary key, name vchar)”));
    query.exec(QObject::tr(“insert into student values (0,’劉明’)”));
    query.exec(QObject::tr(“insert into student values (1,’陳剛’)”));
    query.exec(QObject::tr(“insert into student values (2,’王紅’)”));
    return true;
}

#endif // DATABASE_H

為了在資料庫中能使用中文,我們使用了QObject類的tr()函數。而在下面的main()函數中我們也需要添加相應的代碼來支援中文。

然後將main.cpp的檔案更改如下:

#include <QtGui/QApplication>
#include “widget.h”
#include “database.h”
#include <QTextCodec>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
    if(!createConnection())
        return 1;
    Widget w;
    w.show();
    return a.exec();
}

下面我們開啟widget.ui,設計介面如下:

其中的組件有Table View 和 Line Edit,其餘是幾個按鈕組件。

然後在widget.h中加入標頭檔: #include <QSqlTableModel>

在private中聲明對象:QSqlTableModel *model;

因為我們要在不同的函數中使用model對象,所以我們在這裡聲明它。

我們到widget.cpp檔案中的建構函式裡添加如下代碼:

model = new QSqlTableModel(this);
model->setTable(“student”);
model->setEditStrategy(QSqlTableModel::OnManualSubmit);
model->select(); //選取整個表的所有行
// model->removeColumn(1); //不顯示name屬性列,如果這時添加記錄,則該屬性的值添加不上
ui->tableView->setModel(model);
// ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);   //使其不可編輯

此時運行程式,效果如下:

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

第一,修改操作。

1.我們進入“提交修改”按鈕的單擊事件槽函數,修改如下:

void Widget::on_pushButton_clicked() //提交修改
{
    model->database().transaction(); //開始事務操作
    if (model->submitAll()) {
        model->database().commit(); //提交
    } else {
        model->database().rollback(); //復原
        QMessageBox::warning(this, tr(“tableModel”),
                             tr(“資料庫錯誤: %1″)
                             .arg(model->lastError().text()));
    }
}

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

2.進入“撤銷修改”按鈕單擊事件槽函數,並更改如下:

void Widget::on_pushButton_2_clicked() //撤銷修改
{
     model->revertAll();
}

它只有簡單的一行代碼。

我們需要在widget.cpp檔案中添加標頭檔:

#include <QMessageBox>
#include <QSqlError>

此時運行程式,效果如下:

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

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

model->setEditStrategy(QSqlTableModel::OnManualSubmit);

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

第二,查詢操作。

1.我們進入“查詢”按鈕的單擊事件槽函數,更改如下:

void Widget::on_pushButton_7_clicked() //查詢
{
    QString name = ui->lineEdit->text();
    model->setFilter(QObject::tr(“name = ‘%1′”).arg(name)); //根據姓名進行篩選
    model->select(); //顯示結果
}

我們使用setFilter()函數進行關鍵字篩選,這個函數是對整個結果集進行查詢。為了使用變數,我們使用了QObject類的tr()函數。

2.我們進入“返回全表”按鈕的單擊事件槽函數,更改如下:

void Widget::on_pushButton_8_clicked() //返回全表
{
    model->setTable(“student”);   //重新關聯表
    model->select();   //這樣才能再次顯示整個表的內容
}

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

運行效果如下:

我們輸入一個姓名,點擊“查詢”按鈕後,就可以顯示該記錄了。再點擊“返回全表”按鈕則返回。

第三,排序操作。

我們分別進入“按id升序排列”和“按id降序排列”按鈕的單擊事件槽函數,更改如下:

void Widget::on_pushButton_5_clicked() //升序
{
    model->setSort(0,Qt::AscendingOrder); //id屬性,即第0列,升序排列
    model->select();
}

void Widget::on_pushButton_6_clicked() //降序
{
    model->setSort(0,Qt::DescendingOrder);
    model->select();
}

我們這裡使用了setSort()函數進行排序,它有兩個參數,第一個參數表示按第幾個屬性排序,表頭從左向右,最左邊是第0個屬性,這裡就是id屬性。第二個參數是排序方法,有升序和降序兩種。

運行程式,效果如下:

這是按下“按id降序排列”按鈕後的效果。

第四,刪除操作。

我們進入“刪除選中行”按鈕單擊事件槽函數,進行如下更改:

void Widget::on_pushButton_4_clicked() //刪除當前行
{
    int curRow = ui->tableView->currentIndex().row();
    //擷取選中的行
    model->removeRow(curRow);
    //刪除該行
    int ok = QMessageBox::warning(this,tr(“刪除當前行!”),tr(“你確定”
                                                           “刪除當前行嗎?”),
                         QMessageBox::Yes,QMessageBox::No);
    if(ok == QMessageBox::No)
    {
       model->revertAll(); //如果不刪除,則撤銷
    }
    else model->submitAll(); //否則提交,在資料庫中刪除該行
}

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

運行效果如下:

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

第五,插入操作。

我們進入“添加記錄”按鈕的單擊事件槽函數,更改如下:

void Widget::on_pushButton_3_clicked() //插入記錄
{
    int rowNum = model->rowCount(); //獲得表的行數
   int id = 10;
    model->insertRow(rowNum); //添加一行
    model->setData(model->index(rowNum,0),id);
    //model->submitAll(); //可以直接提交
}

我們在表的最後添加一行,因為在student表中我們設定了id號是主鍵,所以這裡必須使用setData函數給新加的行添加id屬性的值,不然添加行就不會成功。這裡可以直接調用submitAll()函數進行提交,也可以利用“提交修改”按鈕進行提交。

運行程式,效果如下:

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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.