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根據修改資料時的角色進行判斷,修改二維陣列中的值,併發送資料改變的訊號,以此完成資料的更新。