本文章原創於www.yafeilinux.com 轉載請註明出處。
在上一篇的最後我們說到,Qt中使用了自己的機制來避免使用SQL語句,它為我們提供了更簡單的資料庫操作和資料顯示模型。它們分別是唯讀QSqlQueryModel,操作單表的QSqlTableModel和以及可以支援外鍵的QSqlRelationalTableModel。這次我們先講解QSqlQueryModel。
QSqlQueryModel類為SQL的結果集提供了一個唯讀資料模型,下面我們先利用這個類進行一個最簡單的操作。
我們建立Qt4 Gui Application工程,我這裡工程名為queryModel ,然後選中QtSql模組,Base class選QWidget。工程建好後,添加C++ Header File ,命名為database.h,更改其內容如下:
#ifndef DATABASE_H
#define DATABASE_H
#include <QSqlDatabase>
#include <QSqlQuery>
static bool createConnection()
{
QSqlDatabase db = QSqlDatabase::addDatabase(“QSQLITE”);
db.setDatabaseName(“database.db”);
if(!db.open()) return false;
QSqlQuery query;
query.exec(“create table student (id int primary key, name vchar)”);
query.exec(“insert into student values (0,’yafei0′)”);
query.exec(“insert into student values (1,’yafei1′)”);
query.exec(“insert into student values (2,’yafei2′)”);
return true;
}
#endif // DATABASE_H
這裡我們使用了db.setDatabaseName(“database.db”); ,我們沒有再使用以前的記憶體資料庫,而是使用了真實的檔案,這樣後面對資料庫進行的操作就能儲存下來了。
然後進入main.cpp,將其內容更改如下:
#include <QtGui/QApplication>
#include “widget.h”
#include “database.h”
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
if(!createConnection())
return 1;
Widget w;
w.show();
return a.exec();
}
下面我們在widget.ui中添加一個顯示為“查詢”的Push Button,並進入其單擊事件槽函數,更改如下:
void Widget::on_pushButton_clicked()
{
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery(“select * from student”);
model->setHeaderData(0, Qt::Horizontal, tr(“id”));
model->setHeaderData(1, Qt::Horizontal, tr(“name”));
QTableView *view = new QTableView;
view->setModel(model);
view->show();
}
我們建立了QSqlQueryModel類對象model,並用setQuery()函數執行了SQL語句“(“select * from student”);”用來查詢整個student表的內容,可以看到,該類並沒有完全避免SQL語句。然後我們設定了表中屬性顯示時的名字。最後我們建立了一個視圖view,並將這個model模型關聯到視圖中,這樣資料庫中的資料就能在視窗上的表中顯示出來了。
我們在widget.cpp中添加標頭檔:
#include <QSqlQueryModel>
#include <QTableView>
我們運行程式,並按下“查詢”按鍵,效果如下:
我們在工程檔案夾下查看資料庫檔案:
下面我們利用這個模型來操作資料庫。
1.我們在void Widget::on_pushButton_clicked()函數中添加如下代碼:
int column = model->columnCount(); //獲得列數
int row = model->rowCount(); // 獲得行數
QSqlRecord record = model->record(1); //獲得一條記錄
QModelIndex index = model->index(1,1); //獲得一條記錄的一個屬性的值
qDebug() << “column num is:” << column << endl
<< “row num is:” << row << endl
<<”the second record is:” << record << endl
<< “the data of index(1,1) is:”<< index.data();
在我們在widget.cpp中添加標頭檔:
#include <QSqlRecord>
#include <QModelIndex>
#include <QDebug>
此時運行程式,效果如下:
2.當然我們在這裡也可以使用前面介紹過的query執行SQL語句。
例如我們在void Widget::on_pushButton_clicked()函數中添加如下代碼:
QSqlQuery query = model->query();
query.exec(“select name from student where id = 2 “);
query.next();
qDebug() << query.value(0).toString();
這樣就可以輸出表中的值了,你可以運行程式測試一下。
3.當我們將函數改為如下。
void Widget::on_pushButton_clicked()
{
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery(“select * from student”);
model->setHeaderData(0, Qt::Horizontal, tr(“id”));
model->setHeaderData(1, Qt::Horizontal, tr(“name”));
QTableView *view = new QTableView;
view->setModel(model);
view->show();
QSqlQuery query = model->query();
query.exec(“insert into student values (10,’yafei10′)”);
//插入一條記錄
}
這時我們運行程式,效果如下:
我們發現表格中並沒有增加記錄,怎麼回事呢?
我們關閉程式,再次運行,效果如下:
發現這次新的記錄已經添加了。在上面我們執行了添加記錄的SQL語句,但是在添加記錄之前,就已經進行顯示了,所以我們的更新沒能動態顯示出來。為了能讓其動態地顯示我們的更新,我們可以將函數更改如下:
void Widget::on_pushButton_clicked()
{
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery(“select * from student”);
model->setHeaderData(0, Qt::Horizontal, tr(“id”));
model->setHeaderData(1, Qt::Horizontal, tr(“name”));
QTableView *view = new QTableView;
view->setModel(model);
view->show();
QSqlQuery query = model->query();
query.exec(“insert into student values (20,’yafei20′)”);
//插入一條記錄
model->setQuery(“select * from student”); //重新查詢整張表
view->show(); //再次進行顯示
}
這時運行程式,效果如下:
可以看到,這時已經將新添的記錄顯示出來了。
剛開始我們就講到,這個模型預設是唯讀,所以我們在視窗上並不能對錶格中的內容進行修改。但是我們可以建立自己的模型,然後按照我們自己的意願來顯示資料和修改資料。要想使其可讀寫,需要自己的類繼承自QSqlQueryModel,並且重寫setData() 和 flags() 兩個函數。如果我們要改變資料的顯示,就要重寫data() 函數。
下面的例子中我們讓student表的id屬性列顯示紅色,name屬性列可編輯。
1.我們在工程中添加C++ Class,然後Class name設為MySqlQueryModel,Base Class設為QSqlQueryModel,如下:
2.我們將mysqlquerymodel.h中的內容更改如下:
class MySqlQueryModel : public QSqlQueryModel
{
public:
MySqlQueryModel();
//下面三個函數都是虛函數,我們對其進行重載
Qt::ItemFlags flags(const QModelIndex &index) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
QVariant data(const QModelIndex &item, int role=Qt::DisplayRole) const;
//
private:
bool setName(int studentId, const QString &name);
void refresh();
};
然後將mysqlquerymodel.cpp檔案更改如下:
#include “mysqlquerymodel.h”
#include <QSqlQuery>
#include <QColor>
MySqlQueryModel::MySqlQueryModel()
{
}
Qt::ItemFlags MySqlQueryModel::flags(
const QModelIndex &index) const //返回表格是否可更改的標誌
{
Qt::ItemFlags flags = QSqlQueryModel::flags(index);
if (index.column() == 1) //第二個屬性可更改
flags |= Qt::ItemIsEditable;
return flags;
}
bool MySqlQueryModel::setData(const QModelIndex &index, const QVariant &value, int /* role */)
//添加資料
{
if (index.column() < 1 || index.column() > 2)
return false;
QModelIndex primaryKeyIndex = QSqlQueryModel::index(index.row(), 0);
int id = data(primaryKeyIndex).toInt(); //擷取id號
clear();
bool ok;
if (index.column() == 1) //第二個屬性可更改
ok = setName(id, value.toString());
refresh();
return ok;
}
void MySqlQueryModel::refresh() //更新顯示
{
setQuery(“select * from student”);
setHeaderData(0, Qt::Horizontal, QObject::tr(“id”));
setHeaderData(1, Qt::Horizontal, QObject::tr(“name”));
}
bool MySqlQueryModel::setName(int studentId, const QString &name) //添加name屬性的值
{
QSqlQuery query;
query.prepare(“update student set name = ? where id = ?”);
query.addBindValue(name);
query.addBindValue(studentId);
return query.exec();
}
QVariant MySqlQueryModel::data(const QModelIndex &index, int role) const
//更改資料顯示樣式
{
QVariant value = QSqlQueryModel::data(index, role);
if (role == Qt::TextColorRole && index.column() == 0)
return qVariantFromValue(QColor(Qt::red)); //第一個屬性的字型顏色為紅色
return value;
}
在widget.cpp檔案中添加標頭檔:#include “mysqlquerymodel.h”
然後更改函數如下:
void Widget::on_pushButton_clicked()
{
QSqlQueryModel *model = new QSqlQueryModel;
model->setQuery(“select * from student”);
model->setHeaderData(0, Qt::Horizontal, tr(“id”));
model->setHeaderData(1, Qt::Horizontal, tr(“name”));
QTableView *view = new QTableView;
view->setModel(model);
view->show();
MySqlQueryModel *myModel = new MySqlQueryModel; //建立自己模型的對象
myModel->setQuery(“select * from student”);
myModel->setHeaderData(0, Qt::Horizontal, tr(“id”));
myModel->setHeaderData(1, Qt::Horizontal, tr(“name”));
QTableView *view1 = new QTableView;
view1->setWindowTitle(“mySqlQueryModel”); //修改視窗標題
view1->setModel(myModel);
view1->show();
}
運行效果如下:
可以看到我們要的效果已經出來了。