1 模型/視圖架構
1.1 模型
所有的模型都是基於QAbstractItemModel類,這個類定義了一個接口,可以供視圖和委託來訪問數據。
Qt提供的現成模型:
QStringListModel:用來存儲一個簡單的QString項目列表
QStandardItemModel:管理複雜的樹型結構數據項,每一個數據項可以包含任意數據
QFileSystemModel:提供了本地文件系統中文件和目錄的信息
QSqlQueryModel,QSqlTableModel和QSqlRelationalTableModel來訪問數據庫
1.2 視圖
QListView:將模型的數據項顯示爲一個列表
QTableView:將模型的數據顯示成表格
QTreeView:將模型的數據顯示在樹中
1.3 委託
定製數據的渲染和編輯方式
QStyledItemDelegate:使用當前樣式來繪製它的項目,要實現自定義的委託或者要和Qt樣式表一起應用時,建議使用它
QItemDelegate:
#include <QApplication>
#include <QFileSystemModel>
#include <QTreeView>
#include <QListView>
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
//創建文件系統模型
QFileSystemModel model;
//指定根目錄
model.setRootPath(QDir::currentPath());
//創建樹形視圖
QTreeView tree;
//爲視圖指定模型
tree.setModel(&model);
//指定根索引
tree.setRootIndex(model.index(QDir::currentPath()));
//創建列表視圖
QListView list;
list.setModel(&model);
list.setRootIndex(model.index(QDir::currentPath()));
tree.show();
list.show();
return app.exec();
}2 模型類
2.1 模型索引(爲了確保數據的表示與數據的獲取相分離)QModelIndex類提供
QModelIndex是臨時引用,隨着模型的結構改變而改變,
QPersistentModelIndex:用於長時間的引用
獲取數據項的模型索引,必須指定模型的3個屬性:行號,列號和父項的模型索引
2.2 行和列
一個模型可以把它看成一個簡單的表格來訪問,每個數據項可以使用行號和列號來定位
2.3 父項
頂層數據項的父項是QModelIndex()
2.4 項角色
標準的角色由Qt::ItemDataRole來定義
#include <QApplication>
#include <QStandardItemModel>
#include <QTreeView>
#include <QDebug>
#include <QStandardItem>
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
//創建標準數據項模型
QStandardItemModel model;
//獲取模型的根項,根項不可見
QStandardItem * parentItem = model.invisibleRootItem();
//創建標準項item0,並設置顯示文本,圖標和工具提示
QStandardItem *item0 = new QStandardItem;
item0->setText("A");
QPixmap pixmap0(50,50);
pixmap0.fill("red");
item0->setIcon(pixmap0);
item0->setToolTip("indexA");
//就標準項item0作爲根的子項
parentItem->appendRow(item0);
//就創建的標準項item0,作爲新的父項
parentItem = item0;
//爲item0創建子項
QStandardItem *item1 = new QStandardItem;
item1->setText("B");
QPixmap pixmap1(50,50);
pixmap1.fill(("blue"));
item1->setIcon(pixmap1);
item1->setToolTip("indexB");
parentItem->appendRow(item1);
//創建新的標準項,設置文本,圖標,工具提示
QStandardItem *item2 = new QStandardItem;
QPixmap pixmap2(50,50);
pixmap2.fill(("green"));
item2->setData("C",Qt::EditRole);
item2->setData("indexC",Qt::ToolTipRole);
item2->setData(QIcon(pixmap2),Qt::DecorationRole);
parentItem->appendRow(item2);
QTreeView view;
view.setModel(&model);
view.show();
QModelIndex indexA = model.index(0,0,QModelIndex());
qDebug() << "indexA row count:" << model.rowCount(indexA);
QModelIndex indexB = model.index(0,0,indexA);
qDebug() << "indexB text:" << model.data(indexB,Qt::EditRole).toString();
qDebug() << "indexB toolTip:"
<< model.data(indexB,Qt::ToolTipRole);
return app.exec();
}
3 創建新的模型
3.1 創建只讀模型
3.1.1 添加新類:StringListModel,基類:QAbstractListModel,繼承自QObject
3.1.2 修改stringlistmode.h頭文件
因爲QAbstractItemMode本身不存儲任何數據,只提供了一個訪問數據的接口,所以將StringList作爲數據源,
public:
explicit StringListModel(const QStringList &strings,QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const; //返回模型的行數
QVariant data(const QModelIndex &index, int role) const; //返回模型的數據項
//可以在樹和表格視圖的表頭顯示一些內容
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const;
private:
QStringList stringList; //作爲模塊的數據源
添加函數的實現
int StringListModel::rowCount(const QModelIndex &parent) const
{
return stringList.count(); //返回item的個數
}
//獲取索引項對應的數據
QVariant StringListModel::data(const QModelIndex &index, int role) const
{
if (! index.isValid()) return QVariant();
if (index.row() >= stringList.size()) return QVariant();
if (role == Qt::DisplayRole) return stringList.at(index.row());
else return QVariant();
}
//設置表頭對應的數據
QVariant StringListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole) return QVariant();
if (orientation == Qt::Horizontal)
return QString("Column %1").arg(section); //表頭顯示的數據
else
return QString("Row %1").arg(section);
}main.cpp
int main(int argc,char* argv[]) {
QApplication app(argc,argv);
//爲模型構造數據
QStringList list;
list << "a" << "b" << "c" ;
StringListModel model(list);
QListView listView;
listView.setModel(&model);
listView.show();
QTableView tableView;
tableView.setModel(&model);
tableView.show();
return app.exec();
}
3.2 添加編輯功能
添加flags()與setData,flags函數不知道是幹什麼的?有懂得可以留言下
Qt::ItemFlags flags(const QModelIndex &index) const; //
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); //變更數據實現函數
Qt::ItemFlags StringListModel::flags(const QModelIndex &index) const
{
if (!index.isValid()) return Qt::ItemIsEnabled;
return QAbstractItemModel::flags(index)|Qt::ItemIsEditable;
}
bool StringListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::EditRole) {
stringList.replace(index.row(),value.toString()); //更新值
emit dataChanged(index,index); //發出數據變更的信號,左上的index,右下的index
return true;
}
return false;
}修改data()
if (role == Qt::DisplayRole || role == Qt::EditRole) return stringList.at(index.row());
3.3 插入和刪除行
需要添加兩個函數insertRows和removeRows
//row位置,count行數,parent父項索引
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());實現兩個函數
bool StringListModel::insertRows(int row, int count, const QModelIndex &parent)
{
beginInsertRows(QModelIndex(),row,row+count-1);
for (int loop = 0; loop < count; loop++ ) {
stringList.insert(row,"");
}
endInsertRows();
return true;
}
bool StringListModel::removeRows(int row, int count, const QModelIndex &parent)
{
beginRemoveRows(QModelIndex(), row, row+count-1);
for (int loop = 0; loop < count; loop++) {
stringList.removeAt(row);
}
endRemoveRows();
return true;
}