上次提到对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_OBJECT
public:
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_OBJECT
public:
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();
}
}