Qt系列文章之 QAbstractItemModel(下)
本文緊接著上一文介紹如何對(duì)用戶模型剩下的類進(jìn)行實(shí)現(xiàn),并將其集成到視圖并顯示出來(lái)。
QAbstractItemModel
- insertRows(int row, int count, const QModelIndex &parent)
該函數(shù)實(shí)現(xiàn)一次性向表格之中從row位置開始插入count行,一個(gè)簡(jiǎn)單的實(shí)現(xiàn)手段是:
- insertColumns(int column, int count, const QModelIndex &parent)
由于表格固定是兩列,所以此處不做處理。
- removeRows(int row, int count, const QModelIndex &parent)
刪除行與前面的方法類似,此處一個(gè)簡(jiǎn)單實(shí)現(xiàn)如下:
- removeColumns(int column, int count, const QModelIndex &parent)
類似的,此處也不需要對(duì)刪除列進(jìn)行操作:
下一步構(gòu)造一個(gè)簡(jiǎn)單的視圖,實(shí)現(xiàn)對(duì)數(shù)據(jù)的顯示。進(jìn)入main.cpp,對(duì)前期的界面顯示代碼進(jìn)行注釋:
int main(int argc, char *argv[]) {QApplication a(argc, argv);// mainWindow w; // w.show();包含需要的頭文件:
#include <QTableView> #include "customtableview.h"此處使用標(biāo)準(zhǔn)的QTableView來(lái)顯示圖標(biāo),構(gòu)建一個(gè)視圖,構(gòu)建一個(gè)用戶模型示例并將其設(shè)置為視圖的模型,最后顯示視圖。
QTableView view; //構(gòu)造視圖CustomItemModel model; //構(gòu)造模型view.setModel(&model); //設(shè)置視圖的模型view.show(); //顯示視圖編譯運(yùn)行代碼,顯示表格:
再在用戶模型之中加入一個(gè)寫入數(shù)據(jù)的槽函數(shù):
void CustomItemModel::pushData(QString &name, int &age) {m_dataVector->push_back(QPair<QString,int>(name,age));m_checked.push_back(QPair<bool,bool>(false,false));emit dataChanged(createIndex(m_dataVector->size()-1,0),createIndex(m_dataVector->size()-1,1),QVector<int>() << Qt::DisplayRole<<Qt::CheckStateRole); }調(diào)用對(duì)象的槽函數(shù),寫入幾個(gè)測(cè)試數(shù)據(jù):
model.pushData("Jim",28);model.pushData("White",72);運(yùn)行模型:
后面我對(duì)數(shù)據(jù)其他一些角色進(jìn)行修改,增加一個(gè)圖標(biāo)顯示,比如Name列顯示紅色,Age列顯示綠色。
case Qt::DecorationRole://The data to be rendered as a decoration in the form of an icon. (QColor, QIcon or QPixmap){if(index.column()==0) return QColor(255,0,0,255); //Name顯示 紅色if(index.column()==1) return QColor(0,255,0,255); //Age列顯示綠色}運(yùn)行代碼:
再給每個(gè)條目顯示一個(gè)勾選框:
為了方便交互,需要一個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)記錄勾選狀態(tài):
根據(jù)數(shù)據(jù)設(shè)置條目勾選狀態(tài):
case Qt::CheckStateRole:{if(index.column()==0){if(m_checked.at(index.row()).first) return Qt::Checked;else return Qt::Unchecked;}else {if(m_checked.at(index.row()).second) return Qt::Checked;else return Qt::Unchecked;} }根據(jù)用戶選擇記錄勾選狀態(tài):
case Qt::CheckStateRole:{auto cheked = m_checked.at(index.row());if(index.column()==0){m_checked.replace(index.row(),QPair<bool,bool>(value.toBool(),cheked.second));}else{m_checked.replace(index.row(),QPair<bool,bool>(cheked.first,value.toBool()));}emit dataChanged(index, index, QVector<int>() << role);return true;}為了測(cè)試,假設(shè)勾選框勾上,設(shè)置字體為粗體,如果沒(méi)有勾選設(shè)置為非粗體。對(duì)data之中的FontRole編寫算法如下:
case Qt::FontRole:{QFont font;if(index.column()==0? m_checked.at(index.row()).first:m_checked.at(index.row()).second){font.setBold(true);return font;}else {return font;}}編譯運(yùn)行代碼,勾選幾個(gè)條目測(cè)試代碼效果:
那么需要對(duì)insertRows和removeRows做相應(yīng)的修改。修改后用戶模型的頭文件代碼如下:
#ifndef CUSTOMITEMMODEL_H #define CUSTOMITEMMODEL_H#include <QAbstractItemModel> #include <QVector> #include <QMap>class CustomItemModel : public QAbstractItemModel {Q_OBJECTpublic:explicit CustomItemModel(QObject *parent = nullptr);~CustomItemModel();// Header:QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override;// Basic functionality:QModelIndex index(int row, int column,const QModelIndex &parent = QModelIndex()) const override;QModelIndex parent(const QModelIndex &index) const override;int rowCount(const QModelIndex &parent = QModelIndex()) const override;int columnCount(const QModelIndex &parent = QModelIndex()) const override;// Fetch data dynamically:bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;bool canFetchMore(const QModelIndex &parent) const override;void fetchMore(const QModelIndex &parent) override;QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;// Editable:bool setData(const QModelIndex &index, const QVariant &value,int role = Qt::EditRole) override;Qt::ItemFlags flags(const QModelIndex& index) const override;// Add data:bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;// Remove data:bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;public slots:void pushData(QString,int ); //向模型添加一個(gè)數(shù)據(jù)private:QVector<QPair<QString,int>> *m_dataVector = nullptr; //新建一個(gè)儲(chǔ)存數(shù)據(jù)的序列對(duì)象,每個(gè)元素(行)兩個(gè)值,一個(gè)儲(chǔ)存姓名、一個(gè)儲(chǔ)存年齡QList<QString> m_headName; //儲(chǔ)存表頭名稱QVector<QPair<bool,bool>> m_checked{}; //儲(chǔ)存某個(gè)位置是否被勾選 };#endif // CUSTOMITEMMODEL_H用戶模型源文件代碼如下:
#include "customitemmodel.h" #include <QDebug> #include <QColor> #include <QFont> #include <iostream>CustomItemModel::CustomItemModel(QObject *parent): QAbstractItemModel(parent),m_dataVector(new QVector<QPair<QString,int>>{}) {m_dataVector->push_back({"Bob",30});m_headName = {"Name","Age"};m_checked.append(QPair<bool,bool>(false,false)); }CustomItemModel::~CustomItemModel() {if(m_dataVector) {m_dataVector->clear();delete m_dataVector;m_dataVector=nullptr;} }QVariant CustomItemModel::headerData(int section, Qt::Orientation orientation, int role) const {if(role!=Qt::DisplayRole)return QVariant();if(orientation==Qt::Vertical)return QVariant(section);if(orientation==Qt::Horizontal){if(section==0) return QVariant(m_headName[0]);if(section==1) return QVariant(m_headName[1]);}return QVariant(); }bool CustomItemModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) {if (value != headerData(section, orientation, role)) {if(role!=Qt::EditRole) return false;if(orientation==Qt::Vertical) return false;if(section==0) m_headName[0]= value.toString();if(section==1) m_headName[1]=value.toString();emit headerDataChanged(orientation, section, section);return true;}return false; }QModelIndex CustomItemModel::index(int row, int column, const QModelIndex &parent) const {if(row>m_dataVector->size()-1 || row < 0) return QModelIndex();if(column>1 || column<0) return QModelIndex();return createIndex(row,column); }QModelIndex CustomItemModel::parent(const QModelIndex &index) const {// FIXME: Implement me!return QModelIndex(); }int CustomItemModel::rowCount(const QModelIndex &parent) const {return m_dataVector->size(); }int CustomItemModel::columnCount(const QModelIndex &parent) const {return 2; }bool CustomItemModel::hasChildren(const QModelIndex &parent) const {return false; }bool CustomItemModel::canFetchMore(const QModelIndex &parent) const {return false; }void CustomItemModel::fetchMore(const QModelIndex &parent) {// FIXME: Implement me! }QVariant CustomItemModel::data(const QModelIndex &index, int role) const {if (!index.isValid())return QVariant();if(index.row()>m_dataVector->size()-1 || index.row()<0 || index.column()<0 ||index.column()>1)return QVariant();switch(role){case Qt::DisplayRole:{if(index.column()==0){QString name = m_dataVector->at(index.row()).first;return QVariant(name);}if(index.column()==1){int age = m_dataVector->at(index.row()).second;return QVariant(age);}break;}case Qt::TextAlignmentRole:{return Qt::AlignCenter;}case Qt::DecorationRole://The data to be rendered as a decoration in the form of an icon. (QColor, QIcon or QPixmap){if(index.column()==0) return QColor(255,0,0,255); //Name顯示 紅色if(index.column()==1) return QColor(0,255,0,255); //Age列顯示綠色}case Qt::ToolTipRole:{return QVariant();}case Qt::SizeHintRole:{return QVariant();}case Qt::FontRole:{QFont font;if(index.column()==0? m_checked.at(index.row()).first:m_checked.at(index.row()).second){font.setBold(true);return font;}else {return font;}}case Qt::BackgroundRole:{return QVariant();}case Qt::ForegroundRole:{return QVariant();}case Qt::CheckStateRole:{if(index.column()==0){if(m_checked.at(index.row()).first) return Qt::Checked;else return Qt::Unchecked;}else {if(m_checked.at(index.row()).second) return Qt::Checked;else return Qt::Unchecked;}}case Qt::UserRole+1: //用戶自定義角色 預(yù)留{return QVariant();}default:return QVariant();} }bool CustomItemModel::setData(const QModelIndex &index, const QVariant &value, int role) {if (data(index, role) != value){switch (role){case Qt::EditRole:{QString name = m_dataVector->at(index.row()).first;int age = m_dataVector->at(index.row()).second;if(index.column()==0){QPair<QString,int> pair(value.toString(),age);m_dataVector->replace(index.row(),pair);}if(index.column()==1){QPair<QString,int> pair(name,value.toInt());m_dataVector->replace(index.row(),pair);}emit dataChanged(index, index, QVector<int>() << role);return true;}case Qt::CheckStateRole:{auto cheked = m_checked.at(index.row());if(index.column()==0){m_checked.replace(index.row(),QPair<bool,bool>(value.toBool(),cheked.second));}else{m_checked.replace(index.row(),QPair<bool,bool>(cheked.first,value.toBool()));}emit dataChanged(index, index, QVector<int>() << role);return true;}default:return false;}}return false; }Qt::ItemFlags CustomItemModel::flags(const QModelIndex &index) const {if (!index.isValid())return Qt::NoItemFlags;return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable |Qt::ItemIsUserCheckable; // FIXME: Implement me! }bool CustomItemModel::insertRows(int row, int count, const QModelIndex &parent) {if(row<0 || row>m_dataVector->size() || count<1) return false;beginInsertRows(parent, row, row + count - 1);for (quint8 i=0;i<count;i++){QPair<QString,int> newPair{};QPair<bool,bool> state{false,false};m_dataVector->insert(row+i,newPair);m_checked.insert(row+i,state);}endInsertRows();return true; }bool CustomItemModel::insertColumns(int column, int count, const QModelIndex &parent) {beginInsertColumns(parent, column, column + count - 1);endInsertColumns();return false; }bool CustomItemModel::removeRows(int row, int count, const QModelIndex &parent) {if(row<0 || row>m_dataVector->size() || count<1 ) return false;beginRemoveRows(parent, row, row + count - 1);for (quint8 i=0;i<count;i++){if(m_dataVector->size()==0) return true; //判斷是否已經(jīng)刪除完,如果已完,提前退出m_dataVector->remove(row);m_checked.remove(row);}endRemoveRows();return true; }bool CustomItemModel::removeColumns(int column, int count, const QModelIndex &parent) {beginRemoveColumns(parent, column, column + count - 1);// FIXME: Implement me!endRemoveColumns();return false; }void CustomItemModel::pushData(QString name, int age) {m_dataVector->push_back(QPair<QString,int>(name,age));m_checked.push_back(QPair<bool,bool>(false,false));emit dataChanged(createIndex(m_dataVector->size()-1,0),createIndex(m_dataVector->size()-1,1),QVector<int>() << Qt::DisplayRole<<Qt::CheckStateRole); }歡迎同好溝通交流,批評(píng)指正,歡迎關(guān)注我的公號(hào):不如起而行之
總結(jié)
以上是生活随笔為你收集整理的Qt系列文章之 QAbstractItemModel(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 将越狱进行到底 Pod2g邀约众大神组建
- 下一篇: 毕业设计之路(6)——uip