上次提到對student類屬性的描述是侵入式的,這次介紹非侵入式的,其實我也就是借鑒了便准庫中的traits,瞭解的同學應該都知道,不瞭解的可以查查。
我定義了一個類模板,Members,對於類student模板提供了一個特化
/**************************************************author:周翔*e-mail:604487178@qq.com*blog:http://blog.csdn.net/zhx6044***************************************************/#ifndef MEMBERS_HPP#define MEMBERS_HPP#include <QString>#include "student.hpp"template <typename T>class Members{public: static int members() { return 0; } static QString describe(int /*i*/) { return QString(); }};template <>class Members<Student>{public: static int members() { return 3; } static QString describe(int i) { switch (i) { case 0: return "No."; case 1: return "Name"; case 2: return "Sex"; default: break; } return QString(); }};#endif // MEMBERS_HPP
那些model類中的使用像這樣
int DataTableModel::columnCount(const QModelIndex &/*parent*/) const{ return Members<T>::members();}QVariant DataTableModel::headerData(int section, Qt::Orientation orientation, int role) const{ if (role != Qt::DisplayRole) { return QVariant(); } if (orientation == Qt::Vertical) { return QString("row %1").arg(section); } else { return Members<T>::describe(section); } return QVariant();}
前面我們只是提供了簡單的載入顯示,這裡我們允許修改model的資料,這個就用引出代理,在一的時候已經簡單介紹了,如果想詳細瞭解可以直接看文檔(qt的文檔是我見過最好的,是學習的好資料)。我們例子的資料項目是三項,前面兩項都是編輯是可以是文本編輯,最後一個不是男就是女,還是選擇的好。所以我們引入兩個代理類LineEditDelegate和SexComboBox,他們都繼承自QItemDelegate,你也可以繼承自QAbstractItemDelegate,但是用的最多的是QStyledItemDelegate和QItemDelegate,看名字也知道他們之間的區別。下面是LineEditDelegate
/**************************************************author:周翔*e-mail:604487178@qq.com*blog:http://blog.csdn.net/zhx6044***************************************************/#ifndef LINEEDITDELEGATE_HPP#define LINEEDITDELEGATE_HPP#include <QItemDelegate>#include <QLineEdit>class LineEditDelegate : public QItemDelegate{ Q_OBJECTpublic: explicit LineEditDelegate(QObject *parent = 0); QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; signals: public slots: };#endif // LINEEDITDELEGATE_HPP/**************************************************author:周翔*e-mail:604487178@qq.com*blog:http://blog.csdn.net/zhx6044***************************************************/#include "lineeditdelegate.hpp"LineEditDelegate::LineEditDelegate(QObject *parent) : QItemDelegate(parent){}QWidget* LineEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &/*index*/) const{ QLineEdit *w = new QLineEdit(parent); return w;}void LineEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const{ QLineEdit *w = static_cast<QLineEdit*>(editor); w->setText(trUtf8("%1").arg(index.model()->data(index,Qt::DisplayRole).toString()));}void LineEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const{ QString value = static_cast<QLineEdit*>(editor)->text(); model->setData(index,value,Qt::EditRole);}void LineEditDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const{ editor->setGeometry(option.rect);}
SexComboBox
/**************************************************author:周翔*e-mail:604487178@qq.com*blog:http://blog.csdn.net/zhx6044***************************************************/#ifndef SEXCOMBOBOX_HPP#define SEXCOMBOBOX_HPP#include <QItemDelegate>#include <QComboBox>class SexComboBox : public QItemDelegate{ Q_OBJECTpublic: explicit SexComboBox(QObject *parent = 0); QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; signals: public slots: };#endif // SEXCOMBOBOX_HPP/**************************************************author:周翔*e-mail:604487178@qq.com*blog:http://blog.csdn.net/zhx6044***************************************************/#include "sexcombobox.hpp"SexComboBox::SexComboBox(QObject *parent) : QItemDelegate(parent){}QWidget* SexComboBox::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &/*index*/) const{ QComboBox *w = new QComboBox(parent); w->addItems(QStringList() << trUtf8("男") << trUtf8("女")); return w;}void SexComboBox::setEditorData(QWidget *editor, const QModelIndex &index) const{ QComboBox *w = static_cast<QComboBox*>(editor); QString sex = index.model()->data(index,Qt::DisplayRole).toString(); w->setCurrentIndex(w->findText(sex));}void SexComboBox::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const{ QComboBox *w = static_cast<QComboBox*>(editor); QString sex = w->currentText(); model->setData(index,sex,Qt::EditRole);}void SexComboBox::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const{ editor->setGeometry(option.rect);}
如果對這些需要實現的函數不怎麼清除可以看我以前的視圖代理那篇。我想要提醒的注意點是setEditorData和setModelData在設定資料角色時注意,要和model中一致。
實現對model中資料的修改需要在model中實現setData,那我們的student實體類也要支援對修改的支援
student
friend QTextStream& operator <<(QTextStream &out,const Student &t) { out << t.m_no <<" "<< t.m_name <<" "<< t.m_sex << '\n'; return out; } /** * @brief operator [] be called by the function 'data' in model * @param i * @return */ const QString& operator [](int i) const{ switch (i) { case 0: return m_no; case 1: return m_name; // case 2: default: return m_sex; //break; } //return QString(); } /** * @brief operator [] be called by the function 'setData' in model * @param i * @return */ QString& operator [](int i) { switch (i) { case 0: return m_no; case 1: return m_name; // case 2: // return m_sex; default: return m_sex; //break; } }
重載<<將修改過的資料寫迴文件,[]看注釋,關於const和非const請同學自己早資料瞭解
model的setData
bool DataTableModel::setData(const QModelIndex &index, const QVariant &value, int role){ if (role != Qt::EditRole) { return false; } else { m_data[index.row()][index.column()] = value.toString(); return true; } return false;}
啟動並執行結果圖
我修改了我的名字
圖不貼了,有興趣的可以留個郵箱我發代碼
補上save的代碼
void DataTableModel::save(){ QFile file(m_fileName); if (!file.open(QIODevice::WriteOnly)) { emit sig_error("save data failure!"); } else { QTextStream out(&file); for (std::vector<T>::const_iterator it = m_data.begin();it != m_data.end();++it) { out << (*it); } file.close(); }}