首页 > 代码库 > 第61课 模型视图中的委托(上)

第61课 模型视图中的委托(上)

1. Qt模型视图对用户输入的处理

(1)传统的MVC设计模式

技术分享 

(2)Qt中的模型视图设计模式如何处理用户输入?

  ①视图中集成了处理用户输入的功能(即委托)

  ②视图将用户输入作为内部独立的子功能来实现

  ③模型负责组织数据视图负责显示数据委托则用于编辑修改数据

技术分享 

2. 模型视图中的委托

(1)委托(Delegate)是视图中处理用户输入的部件(如编辑框、单选按钮等)

(2)视图可以设置委托对象用于处理用户输入

(3)委托对象负责创建和显示用户输入的上下文(内容),如编辑框的创建和显示。

(4)委托类的继承图

技术分享 

3. 委托中的编辑器

(1)委托能够提供编辑时需要的上下文环境编辑器

(2)不同委托提供的编辑器类型不同(如文本框、单选框等)

(3)编辑器从模型获取数据并将编辑结果返回模型

技术分享 

(4)委托中的关键函数

  ①createEditor需要编辑数据时创建编辑器组件

  ②updateEditorGeometry:更新编辑器组件的大小

  ③setEditorData:通过索引从模型中获取数据,并将数据显示到编辑器中

  ④setModelData:编辑后的新数据写入模型

(5)委托中的关键信号

  ①void closeEditor(QWidget* editor):编辑器组件关闭信号

  ②void commitData(QWidget* editor):新数据提交信号

【编程实验】视图中的委托以及委托的关键函数与信号

技术分享

//main.cpp

技术分享
#include "Widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}
View Code

//Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTableView>
#include <QStandardItemModel>
#include <QPushButton>
#include "SubStyledItemDelegate.h"

class Widget : public QWidget
{
    Q_OBJECT

    QTableView m_view;
    QStandardItemModel m_model;
    QPushButton m_testBtn;
    SubStyledItemDelegate m_delegate;

    void initView();
    void initModel();
private slots:
    void onTestBtnClicked();
public:
    Widget(QWidget *parent = 0);
    ~Widget();
};

#endif // WIDGET_H

//Widget.cpp

#include "Widget.h"
#include <QModelIndex>
#include <QDebug>

Widget::Widget(QWidget *parent): QWidget(parent)
{
    initView();
    initModel();

    m_testBtn.setParent(this);
    m_testBtn.move(10, 120);
    m_testBtn.resize(300, 30);
    m_testBtn.setText("Test");

    connect(&m_testBtn,SIGNAL(clicked()), this, SLOT(onTestBtnClicked()));
}

void Widget::initView()
{    
    m_view.setParent(this);
    m_view.move(10, 10);
    m_view.resize(300, 100);

    m_view.setModel(&m_model);
    m_view.setItemDelegate(&m_delegate);
}

void Widget::initModel()
{
    QStandardItem* root = m_model.invisibleRootItem();
    QStandardItem* itemA = new QStandardItem();
    QStandardItem* itemB = new QStandardItem();
    QStandardItem* itemC = new QStandardItem();
    QStandardItem* itemD = new QStandardItem();

    itemA->setData("A", Qt::DisplayRole);
    itemB->setData("B", Qt::DisplayRole);
    itemC->setData("C", Qt::DisplayRole);
    itemD->setData("D", Qt::DisplayRole);

    root->setChild(0, 0, itemA);
    root->setChild(0, 1, itemB);
    root->setChild(1, 0, itemC);
    root->setChild(1, 1, itemD);
}

void Widget::onTestBtnClicked()
{
    qDebug() <<"Model Data:";

    for(int i=0; i<m_model.rowCount(); i++)
    {
        qDebug() << "Row:" << i;
        for(int j=0; j<m_model.columnCount(); j++)
        {
            QModelIndex index = m_model.index(i, j, QModelIndex());
            QString text = index.data(Qt::DisplayRole).toString();

            qDebug() << text;
        }

        qDebug() << endl;
    }

    qDebug() << "Current View Delegate: " << m_view.itemDelegate();
}

Widget::~Widget()
{

}

//SubStyleItemDelegate.h

#ifndef SUBSTYLEDITEMDELEGATE_H
#define SUBSTYLEDITEMDELEGATE_H

#include <QStyledItemDelegate>

class SubStyledItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

protected slots:
    void onCloseEditor(QWidget* editor);
    void onCommitData(QWidget* editor);

public:
    explicit SubStyledItemDelegate(QObject* parent = 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, 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;
};

#endif // SUBSTYLEDITEMDELEGATE_H

//SubStyleItemDelegate.cpp

#include "SubStyledItemDelegate.h"
#include <QDebug>

SubStyledItemDelegate::SubStyledItemDelegate(QObject* parent):
    QStyledItemDelegate(parent)
{
    connect(this ,SIGNAL(closeEditor(QWidget*)), this, SLOT(onCloseEditor(QWidget*)));
    connect(this ,SIGNAL(commitData(QWidget*)), this, SLOT(onCommitData(QWidget*)));

}

QWidget *SubStyledItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    qDebug() << "SubStyledItemDelegate::createEditor";
    return QStyledItemDelegate::createEditor(parent, option, index);
}

void SubStyledItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    qDebug() << "SubStyledItemDelegate::updateEditorGeometry";
    QStyledItemDelegate::updateEditorGeometry(editor, option, index);
}

void SubStyledItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    qDebug() << "SubStyledItemDelegate::setEditorData";
    return QStyledItemDelegate::setEditorData(editor, index);
}

void SubStyledItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    qDebug() << "SubStyledItemDelegate::setModelData";
    return QStyledItemDelegate::setModelData(editor, model, index);
}

void SubStyledItemDelegate::onCloseEditor(QWidget *editor)
{
    Q_UNUSED(editor);
    qDebug() <<"SubStyledItemDelegate::onCloseEditor" ;
}

void SubStyledItemDelegate::onCommitData(QWidget *editor)
{
    Q_UNUSED(editor);
    qDebug() <<"SubStyledItemDelegate::onCommitData" ;
}

输出结果:

/*
SubStyledItemDelegate::createEditor
SubStyledItemDelegate::updateEditorGeometry
SubStyledItemDelegate::setEditorData
SubStyledItemDelegate::onCommitData
SubStyledItemDelegate::setModelData
SubStyledItemDelegate::setEditorData
SubStyledItemDelegate::onCloseEditor
Model Data:
Row: 0
"A"
"C"


Row: 1
"C"
"D"


Current View Delegate:  SubStyledItemDelegate(0x23fe40)
*/

4. 小结

(1)委托(Delegate)是视图中处理用户输入的部件

(2)视图可以设置委托对象,用于处理用户输入

(3)委托能够提供编辑时需要的上下文环境编辑器

(4)不同委托提供的编辑器类型不同(文本框、单选框等)

(5)编辑器从模型中获取数据,并将编辑结果返回模型

第61课 模型视图中的委托(上)