Qt自定義代理與實例


1. 代理的定義

代理(Delegate)就是在視圖組件上為編輯數據提供編輯器,如在表格組件中編輯一個單元格的數據時,缺省是使用一個QLineEdit編輯框。代理負責從數據模型獲取相應的數據,然后顯示在編輯器里,修改數據后,又將其保存到數據模型中。

QAbstractItemDelegate是所有代理類的基類,作為抽象類,它不能直接使用。它的一個子類QStyledItemDelegate,是Qt的視圖組件缺省使用的代理類。

對於一些特殊的數據編輯需求,例如只允許輸入整型數,使用一個QSpinBox作為代理組件更恰當,從列表中選擇數據時使用一個QComboBox作為代理組件更好。這時,就可以從QStyledItemDelegate繼承創建自定義代理類

2. 自定義代理的功能

當我們導入數據文件進行編輯時,QTableView組件為每個單元格提供的是缺省的代理編輯組件,就是一個QLineEdit組件。

在編輯框里可以輸入任何數據,所以比較通用。但是有些情況下,希望根據數據的類型限定使用不同的編輯組件,例如第1列我們要求是整數,使用QSpinBox作為編輯組件更合適

3. 自定義代理類的基本要求

image-20210726092312517

不管從QStyledItemDelegate還是QItemDelegate繼承設計自定義代理組件,都必須實現如下的4個函數:

  • createEditor()函數創建用於編輯模型數據的 widget組件,如一個QSpinBox組件,或一個QComboBox 組件;
  • setEditorData()函數從數據模型獲取數據,供 widget組件進行編輯;
  • setModelData()將 widget上的數據更新到數據模型;
  • updateEditorGeometry()用於給widget組件設置一個合適的大小。

4. 實例

4.1 效果演示

我們要實現的就是,弄一個表格,當我們編輯數據的時候,能夠有下圖所示的效果

image-20210726092952169

而不是單獨的文本編輯框,還有下面這種spinbox

image-20210726093118857

4.2 關鍵代碼分析

為了方便起見,我們采用spinbox的代理類來講解具體的代碼

首先要記得,我們得實現4個函數

createEditor() 創建用於編輯模型數據的 widget組件

static string MyBlog = "https://www.cnblogs.com/wanghongyang";

QWidget *SpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setRange(0,10000);
    editor->installEventFilter(const_cast<SpinDelegate*>(this));

    return editor;
}

這里創建了一個spinbox組件,設置范圍,安裝過濾器,我們來看看這個過濾器的用法

void QObject::installEventFilter(QObject *filterObj)

在這個對象上安裝一個事件過濾器filterObj

事件篩選器是一個對象,它接收發送到此對象的所有事件。過濾器可以停止事件,也可以將事件轉發給該對象。事件過濾器filterObj通過其eventFilter()函數接收事件。eventFilter()函數必須返回true,如果事件應該被過濾(即停止);否則它必須返回false。

如果在單個對象上安裝多個事件篩選器,最后安裝的篩選器將首先激活。

看到這里const_cast有些不明白,我們再來看看const_cast

const_cast轉換符是用來移除變量的const或volatile限定符

**setEditorData() **從數據模型獲取數據,供 widget組件進行編輯

void SpinDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
    int value =index.model()->data(index).toInt();
    QSpinBox *box = static_cast<QSpinBox*>(editor);
    box->setValue(value);
}

函數重模型中獲得數據,然后設置數據給組件進行編輯

setModelData() 將 widget上的數據更新到數據模型

void SpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const
{
    QSpinBox *box = static_cast<QSpinBox*>(editor);
    int value = box->value();

    model->setData(index,value);
}

代碼淺顯易懂,不過多贅述

updateEditorGeometry() 給widget組件設置一個合適的大小

void SpinDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect);
}

接下來我們看看這些函數的具體使用

在main函數中設置代理,通過列的方式

SpinDelegate spinDelegate;
tableView.setItemDelegateForColumn(3,&spinDelegate);

這樣就可以使用自定義代理了

4. 擴展

其他一些關於模型的細節,大家可以看看我之前的文章

https://www.cnblogs.com/wanghongyang/p/15017253.html

https://www.cnblogs.com/wanghongyang/p/15037968.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM