Qt Model/View理解(三)---桥梁Delegate

上两节中介绍了如何构造model,并与数据关联,在不同的显示控件中展示数据的方式。都是以只读方式读取数据,然后显示出来,没有对数据源进行写操作。今天将以第2节为基础,实现修改并显示数据源的功能。这里开始引入了代理(Delegate)的概念。

代理在模型和视图中间桥梁的作用,它可以渲染数据项,并通知模型和视图进行数据更新。

实现修改第2节中的数据项的思路:

1.双击任何一个空白处,弹出一个LineEdit;

2.获取原先显示的数据到LineEdit控件中,编辑数据;

3.将新的数据回写到模型和二维数组中,视图和模型自动就会关联并显示新的数据。

下面开始写代码:

一、QAbstractItemDelegate是模型/视图框架中代理的基类。默认的代理实现由QStyledItemDelegate类提供。我们实现一个类LineEditDelegate,继承自QStyledItemDelegate。

class LineEditDeleget : public QStyledItemDelegate
{
public:
    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;
};
//创建编辑器,这些编辑器是一些控件,如Label,LineEdit,Combox等
QWidget *LineEditDeleget::createEditor(QWidget * parent, const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/) const
{
    QLineEdit *line = new QLineEdit(parent);
    return line;
}

//从model中取出数据,放到编辑器中
void	LineEditDeleget::setEditorData(QWidget * editor, const QModelIndex & index) const
{
    QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
    QString str = index.model()->data(index,Qt::DisplayRole).toString();//获取model中的数据,角色为DisplayRole
    lineEdit->setText(str);
}

//将编辑器中的数据更新到model中
void	LineEditDeleget::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
{
    QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
    model->setData(index,lineEdit->text(),Qt::EditRole);
}

我们通过重载了3个函数,createEditor函数中创建了一个LineEdit控件,当双击表格项时该LineEdit控件就会显示出来;接下来,我们要把原先model中显示的数据放到LineEdit控件中,主要是通过index下标来获取值,由setEditorData函数实现。最后,修改的新数据,目前只是存在于LineEdit控件上,并没有写入model中。通过setModelData函数,将对应的index下标的model数据进行更新。注意,此时修改数据时的角色类型是Qt::EditRole。

二、代理类更新了model的数据,然而,model类中必须要做出相应的处理才能真正实现数据更新。TableModel类中要添加2个新的接口flags和setData。最后如下:

class TableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    TableModel(QObject *parent = 0);
    ~TableModel();
    //QAbstractTableModel 中3个必须重新实现的虚函数
    int	rowCount(const QModelIndex & parent = QModelIndex()) const;
    int	columnCount(const QModelIndex & parent = QModelIndex()) const;
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;

    Qt::ItemFlags flags(const QModelIndex & index) const;
    bool setData(const QModelIndex & index, const QVariant & value, int role);

private:
    int num[ROW][COL];
    int nn;
};
//可编辑表格添加函数
Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
    Qt::ItemFlags flags = QAbstractItemModel::flags(index);
    flags |= Qt::ItemIsEditable;
    return flags;
}

bool TableModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    if (index.isValid() && role == Qt::EditRole)
     {
         num[index.row()][index.column()] = value.toInt();
         emit dataChanged(index, index);
         return true;
     }
     return false;
}

flags函数作用主要表示当前的model并不是一个只读的,还有可编辑的功能。当代理类修改了model中的数据时,model类会调用setData根据修改数据时的角色进行判断,修改二维数组中的值,并发送数据改变的信号,以此完成数据的更新。



猜你喜欢

转载自blog.csdn.net/lutao614/article/details/80881800
今日推荐