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(); }
//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)编辑器从模型中获取数据,并将编辑结果返回模型