QtCreator 模塊/視圖編程( 一) 模型類,自定義模型QStringListModel,QStandardItemModel,QFileSystemModel,QSqlQueryModel,

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;
}










發佈了44 篇原創文章 · 獲贊 12 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章