文章目录

  • 1 初探QT模型视图中的委托
  • 2 自定义委托
  • 3 深度解析视图与委托
    • 3.1 实例1:自定义视图显示方式
    • 3.2 实例2:自定义视图显示方式提升用户体验

1 初探QT模型视图中的委托

首先来看一个问题:模型负责组织数据,视图负责显示数据,如何编辑数据呢?

我们先来看一下传统的MVC设计模式:

Qt中的模型视图设计模型如何处理用户输入呢?

  • 视图中集成了处理用户输入的功能。
  • 视图将用户输入作为内部独立的子功能而实现。


模型视图中的委托:

  • 委托(Delegate)是视图中处理用户输入的部件。
  • 视图可以设置委托对象用于处理用户输入。
  • 委托对象负责创建和显示用户输入上下文。
    • 如:编辑框的创建和显示。

委托中的编辑器:

  • 委托能够提供编辑时需要的上下文环境(编辑器)。
  • 不同委托提供的编辑器类型不同(文本框、单选框,等)。
  • 编辑器从模型获取数据,并将编辑结果返回模型。


委托中的关键函数:

  • createEditor:需要编辑数据时,创建编辑器组件。
  • updateEditorGeometry:更新编辑器组件的大小。
  • setEditorData:通过索引从模型中获取数据。
  • setModelData:将编辑后的新数据返回模型。

委托中的关键信号:

  • void closeEditor(QWidget* editor):编辑器组件关闭信号。
  • void commitData(QWidget* editor):新数据提交信号。

对模型中的委托进行一下简单的总结:

  • 委托是视图中处理用户输入的部件。
  • 视图可以设置委托对象用于处理用户输入。
  • 委托能够提供编辑时需要的上下文环境(编辑器)。
  • 不同委托提供的编辑器类型不同(文本框、单选框等)。
  • 编辑器从模型中获取数据,并将编辑结果返回模型。

如下为测试代码:

SubStyledItemDelegate.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

SubStyledItemDelegate.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";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)
{qDebug() << "SubStyledItemDelegate::onCloseEditor";
}void SubStyledItemDelegate::onCommitData(QWidget* editor)
{qDebug() << "SubStyledItemDelegate::onCommitData";
}

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QtGui/QWidget>
#include <QTableView>
#include <QStandardItemModel>
#include <QPushButton>
#include "SubStyledItemDelegate.h"class Widget : public QWidget
{Q_OBJECTQTableView 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_view.setModel(&m_model);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.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()
{}

main.cpp:

#include <QtGui/QApplication>
#include "Widget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

一次完成的修改数据的流程输入结果如下:

当结束输入时才触发commitData。


2 自定义委托

首先来看一下委托的本质:

  • 为视图提供数据编辑的上下文环境。
  • 产生界面元素的工厂类。
  • 能够使用和设置模型中的数据。

问题:如何自定一个委托类?

自定义委托时需要重写的函数:

  1. 重写creatorEditor成员函数:
  2. 重写updateEditorGeometry成员函数。
  3. 重写setEditorData成员函数。
  4. 重写setModelData成员函数。
  5. 重写paint成员函数(可选)。

    思考一下:自定义委托时重写的函数由谁调用?视图调用。

对自定义委托类总结一下:

  • 自定义委托类时需要重写相应的成员函数。
  • 根据需要创建编辑组件并设置组件中的数据。
  • 编辑结束后将数据返回模型。
  • 成员函数的参数携带了数据存取时需要的信息。

如下为自定义委托类的代码:

CustomizedItemDelegate.h:

#ifndef CUSTOMIZEDITEMDELEGATE_H
#define CUSTOMIZEDITEMDELEGATE_H#include <QItemDelegate>
#include <QModelIndex>class CustomizedItemDelegate : public QItemDelegate
{Q_OBJECTmutable QModelIndex m_index;
protected slots:void onCloseEditor(QWidget*);
public:explicit CustomizedItemDelegate(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;void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};#endif // CUSTOMIZEDITEMDELEGATE_H

CustomizedItemDelegate.cpp:

#include "CustomizedItemDelegate.h"
#include <QCheckBox>
#include <QComboBox>CustomizedItemDelegate::CustomizedItemDelegate(QObject *parent) :QItemDelegate(parent)
{connect(this, SIGNAL(closeEditor(QWidget*)), this, SLOT(onCloseEditor(QWidget*)));
}QWidget* CustomizedItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{QWidget* ret = NULL;m_index = index;if( index.data().type() == QVariant::Bool ){QCheckBox* cb = new QCheckBox(parent);cb->setText("Check to TRUE");ret = cb;}else if( index.data().type() == QVariant::Char ){QComboBox* cb = new QComboBox(parent);cb->addItem("A");cb->addItem("B");cb->addItem("C");cb->addItem("D");ret = cb;}else{ret = QItemDelegate::createEditor(parent, option, index);}return ret;
}void CustomizedItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{editor->setGeometry(option.rect);
}void CustomizedItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{if( index.data().type() == QVariant::Bool ){QCheckBox* cb = dynamic_cast<QCheckBox*>(editor);if( cb != NULL ){cb->setChecked(index.data().toBool());}}else if( index.data().type() == QVariant::Char ){QComboBox* cb = dynamic_cast<QComboBox*>(editor);if( cb != NULL ){for(int i=0; i<cb->count(); i++){if( cb->itemText(i) == index.data().toString() ){cb->setCurrentIndex(i);break;}}}}else{QItemDelegate::setEditorData(editor, index);}
}void CustomizedItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{if( index.data().type() == QVariant::Bool ){QCheckBox* cb = dynamic_cast<QCheckBox*>(editor);if( cb != NULL ){model->setData(index, cb->isChecked(), Qt::DisplayRole);}}else if( index.data().type() == QVariant::Char ){QComboBox* cb = dynamic_cast<QComboBox*>(editor);if( cb != NULL ){model->setData(index, cb->currentText().at(0), Qt::DisplayRole);}}else{QItemDelegate::setModelData(editor, model, index);}
}void CustomizedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{if( m_index != index ){QItemDelegate::paint(painter, option, index);}
}void CustomizedItemDelegate::onCloseEditor(QWidget*)
{m_index = QModelIndex();
}

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QtGui/QWidget>
#include <QTableView>
#include <QStandardItemModel>
#include <QPushButton>
#include "CustomizedItemDelegate.h"class Widget : public QWidget
{Q_OBJECTQTableView m_view;QStandardItemModel m_model;CustomizedItemDelegate m_delegate;void initView();void initModel();public:Widget(QWidget* parent = 0);~Widget();
};#endif // WIDGET_H

Widget.cpp:

#include "Widget.h"
#include <QStandardItem>
#include <QModelIndex>
#include <QStringList>
#include <QDebug>Widget::Widget(QWidget* parent) : QWidget(parent)
{initView();initModel();m_view.setModel(&m_model);for(int i=0; i<m_model.columnCount(); i++){m_view.setColumnWidth(i, 125);}
}void Widget::initView()
{m_view.setParent(this);m_view.move(10, 10);m_view.resize(500, 200);m_view.setItemDelegate(&m_delegate);
}void Widget::initModel()
{QStandardItem* root = m_model.invisibleRootItem();QStringList hl;QStandardItem* itemA1 = new QStandardItem();QStandardItem* itemB1 = new QStandardItem();QStandardItem* itemC1 = new QStandardItem();QStandardItem* itemA2 = new QStandardItem();QStandardItem* itemB2 = new QStandardItem();QStandardItem* itemC2 = new QStandardItem();hl.append("Language");hl.append("Level");hl.append("Script");m_model.setHorizontalHeaderLabels(hl);itemA1->setData("Delphi", Qt::DisplayRole);itemB1->setData(QChar('A'), Qt::DisplayRole);itemC1->setData(false, Qt::DisplayRole);itemA2->setData("Perl", Qt::DisplayRole);itemB2->setData(QChar('B'), Qt::DisplayRole);itemC2->setData(true, Qt::DisplayRole);root->setChild(0, 0, itemA1);root->setChild(0, 1, itemB1);root->setChild(0, 2, itemC1);root->setChild(1, 0, itemA2);root->setChild(1, 1, itemB2);root->setChild(1, 2, itemC2);
}Widget::~Widget()
{}

main.cpp:

#include <QtGui/QApplication>
#include "Widget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

3 深度解析视图与委托

深度的思考:委托是视图的构成部分,那么委托是否帮助视图显示具体数据呢?

分析:Qt中的委托作为视图的内部组件而存在,因此,委托是视图的一部分。必然,委托需要承担数据显示的部分工作。

关于视图和委托:

  • 视图负责确定数据项的组织显示方式(列表、树形、表格)。
  • 委托负责具体数据项的显示和编辑(数据值、编辑器)。
  • 视图和委托共同完成数据显示功能和数据编辑功能。
  • 重写委托的paint函数自定义数据项显示方式。
  • 重写委托的editorEvent函数处理交互事件。

3.1 实例1:自定义视图显示方式

思考:如何改变视图默认的数据显示方式?

自定义委托的默认数据显示方式:

  1. 重写paint成员函数。
  2. 在paint中自定义数据显示方式。
  3. 重写editorEvent成员函数。
  4. 在editorEvent中处理交互事件。

在paint中自定义数据显示方式:

在editorEvent中处理交互事件:

CustomizedItemDelegate.h:

#ifndef CUSTOMIZEDITEMDELEGATE_H
#define CUSTOMIZEDITEMDELEGATE_H#include <QItemDelegate>
#include <QModelIndex>class CustomizedItemDelegate : public QItemDelegate
{Q_OBJECTpublic:explicit CustomizedItemDelegate(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;void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
};#endif // CUSTOMIZEDITEMDELEGATE_H

CustomizedItemDelegate.cpp:

#include "CustomizedItemDelegate.h"
#include <QComboBox>
#include <QMouseEvent>
#include <QApplication>
#include <QDebug>CustomizedItemDelegate::CustomizedItemDelegate(QObject *parent) :QItemDelegate(parent)
{}QWidget* CustomizedItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{QWidget* ret = NULL;if( index.data().type() == QVariant::Char ){QComboBox* cb = new QComboBox(parent);cb->addItem("A");cb->addItem("B");cb->addItem("C");cb->addItem("D");ret = cb;}else{ret = QItemDelegate::createEditor(parent, option, index);}return ret;
}void CustomizedItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{editor->setGeometry(option.rect);
}void CustomizedItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{if( index.data().type() == QVariant::Char ){QComboBox* cb = dynamic_cast<QComboBox*>(editor);if( cb != NULL ){for(int i=0; i<cb->count(); i++){if( cb->itemText(i) == index.data().toString() ){cb->setCurrentIndex(i);break;}}}}else{QItemDelegate::setEditorData(editor, index);}
}void CustomizedItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{if( index.data().type() == QVariant::Char ){QComboBox* cb = dynamic_cast<QComboBox*>(editor);if( cb != NULL ){model->setData(index, cb->currentText().at(0), Qt::DisplayRole);}}else{QItemDelegate::setModelData(editor, model, index);}
}void CustomizedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{if( index.data().type() == QVariant::Bool ){bool data = index.data(Qt::DisplayRole).toBool();QStyleOptionButton checkBoxStyle;checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off;checkBoxStyle.state |= QStyle::State_Enabled;checkBoxStyle.rect = option.rect;checkBoxStyle.rect.setX(option.rect.x() + option.rect.width() / 2 - 6);QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxStyle, painter);}else{QItemDelegate::paint(painter, option, index);}
}bool CustomizedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{bool ret = true;if( index.data().type() == QVariant::Bool ){QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(event);if( (event->type() == QEvent::MouseButtonPress) && option.rect.contains(mouseEvent->pos()) ){bool data = index.data(Qt::DisplayRole).toBool();qDebug() << "set model data: " << !data;qDebug() << model->setData(index, !data, Qt::DisplayRole);}}else{ret = QItemDelegate::editorEvent(event, model, option, index);}return ret;
}

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QtGui/QWidget>
#include <QTableView>
#include <QStandardItemModel>
#include "CustomizedItemDelegate.h"class Widget : public QWidget
{Q_OBJECTQTableView m_view;QStandardItemModel m_model;CustomizedItemDelegate m_delegate;void initView();void initModel();public:Widget(QWidget* parent = 0);~Widget();
};#endif // WIDGET_H

Widget.cpp:

#include "Widget.h"
#include <QStandardItem>
#include <QModelIndex>
#include <QStringList>
#include <QDebug>Widget::Widget(QWidget* parent) : QWidget(parent)
{initView();initModel();m_view.setModel(&m_model);for(int i=0; i<m_model.columnCount(); i++){m_view.setColumnWidth(i, 125);}
}void Widget::initView()
{m_view.setParent(this);m_view.move(10, 10);m_view.resize(500, 200);m_view.setItemDelegate(&m_delegate);
}void Widget::initModel()
{QStandardItem* root = m_model.invisibleRootItem();QStringList hl;QStandardItem* itemA1 = new QStandardItem();QStandardItem* itemB1 = new QStandardItem();QStandardItem* itemC1 = new QStandardItem();QStandardItem* itemA2 = new QStandardItem();QStandardItem* itemB2 = new QStandardItem();QStandardItem* itemC2 = new QStandardItem();hl.append("Language");hl.append("Level");hl.append("Script");m_model.setHorizontalHeaderLabels(hl);itemA1->setData("Delphi", Qt::DisplayRole);itemB1->setData(QChar('A'), Qt::DisplayRole);itemC1->setData(false, Qt::DisplayRole);itemA2->setData("Perl", Qt::DisplayRole);itemB2->setData(QChar('B'), Qt::DisplayRole);itemC2->setData(true, Qt::DisplayRole);root->setChild(0, 0, itemA1);root->setChild(0, 1, itemB1);root->setChild(0, 2, itemC1);root->setChild(1, 0, itemA2);root->setChild(1, 1, itemB2);root->setChild(1, 2, itemC2);
}Widget::~Widget()
{}

main.cpp:

#include <QtGui/QApplication>
#include "Widget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

3.2 实例2:自定义视图显示方式提升用户体验

下面看一个实例的分析与改进:

考虑一下:如何改进程序界面使其拥有更好的用户体验?

改进思路:将Progress从纯文本的显示方式改变为进度条+文本显示的方式;可以直观的让用户感受到当前的任务进度。

解决方案:

  1. 自定义新的委托类。
  2. 在paint成员函数中绘制进度条显示方式。
  3. 在editorEvent成员函数中禁止数据编辑操作。

在paint成员函数中绘制进度条显示:

在editorEvent成员函数中禁止数据编辑操作:

任务进度模拟:

  1. 定义计时器用于模拟任务进度。
  2. 定义计时器槽函数void timerTimeOut()。
  3. 在槽函数中修改模型中的数据。

实例扩展:在实际工程项目中,可以使用后台线程根据实际的任务情况更新模型中的数据,从而更新数据的界面显示。

总结一下自定义视图数据显示的方法:

实例代码如下:

CustomizedItemDelegate.h:

#ifndef CUSTOMIZEDITEMDELEGATE_H
#define CUSTOMIZEDITEMDELEGATE_H#include <QItemDelegate>class CustomizedItemDelegate : public QItemDelegate
{Q_OBJECT
public:explicit CustomizedItemDelegate(QObject *parent = 0);void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
};#endif // CUSTOMIZEDITEMDELEGATE_H

CustomizedItemDelegate.cpp:

#include "CustomizedItemDelegate.h"
#include <QApplication>
#include <QEvent>CustomizedItemDelegate::CustomizedItemDelegate(QObject *parent) :QItemDelegate(parent)
{}void CustomizedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{if( index.data().type() == QVariant::Int ){const int DELTA = 4;int progress = index.data().toInt();QStyleOptionProgressBar progressBarOption;int top = option.rect.top() + DELTA;int left = option.rect.left() + DELTA;int width = option.rect.width() - 2 * DELTA;int height = option.rect.height() - 2 * DELTA;progressBarOption.rect = QRect(left, top, width, height);progressBarOption.minimum = 0;progressBarOption.maximum = 100;progressBarOption.progress = progress;progressBarOption.textVisible = true;progressBarOption.text = QString().sprintf("%d", progress) + "%";progressBarOption.textAlignment = Qt::AlignCenter;QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);}else{QItemDelegate::paint(painter, option, index);}
}bool CustomizedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{bool ret = true;if( event->type() != QEvent::MouseButtonDblClick ){ret = QItemDelegate::editorEvent(event, model, option, index);}return ret;
}

Widget.h:

#ifndef WIDGET_H
#define WIDGET_H#include <QtGui/QWidget>
#include <QTableView>
#include <QStandardItemModel>
#include <QTimer>
#include "CustomizedItemDelegate.h"class Widget : public QWidget
{Q_OBJECTQTableView m_view;QStandardItemModel m_model;CustomizedItemDelegate m_delegate;QTimer m_timer;void initView();void initModel();
private slots:void timerTimeout();
public:Widget(QWidget* parent = 0);~Widget();
};#endif // WIDGET_H

Widget.cpp:

#include "Widget.h"
#include <QStandardItem>
#include <QModelIndex>
#include <QStringList>
#include <QModelIndex>
#include <QDebug>Widget::Widget(QWidget* parent) : QWidget(parent)
{initView();initModel();m_view.setModel(&m_model);for(int i=0; i<m_model.columnCount(); i++){m_view.setColumnWidth(i, 200);}connect(&m_timer, SIGNAL(timeout()), this, SLOT(timerTimeout()));m_timer.setParent(this);m_timer.start(500);
}void Widget::initView()
{m_view.setParent(this);m_view.move(10, 10);m_view.resize(500, 200);m_view.setItemDelegate(&m_delegate);
}void Widget::initModel()
{QStandardItem* root = m_model.invisibleRootItem();QStringList hl;QStandardItem* itemA1 = new QStandardItem();QStandardItem* itemB1 = new QStandardItem();QStandardItem* itemA2 = new QStandardItem();QStandardItem* itemB2 = new QStandardItem();hl.append("Task");hl.append("Progress");m_model.setHorizontalHeaderLabels(hl);itemA1->setData("Delphi", Qt::DisplayRole);itemB1->setData(70, Qt::DisplayRole);itemA2->setData("Perl", Qt::DisplayRole);itemB2->setData(60, Qt::DisplayRole);root->setChild(0, 0, itemA1);root->setChild(0, 1, itemB1);root->setChild(1, 0, itemA2);root->setChild(1, 1, itemB2);
}void Widget::timerTimeout()
{QModelIndex i1 = m_model.index(0, 1, QModelIndex());QModelIndex i2 = m_model.index(1, 1, QModelIndex());QVariant v1 = (i1.data().toInt() + 1) % 100;QVariant v2 = (i2.data().toInt() + 3) % 100;m_model.setData(i1, v1, Qt::DisplayRole);m_model.setData(i2, v2, Qt::DisplayRole);
}Widget::~Widget()
{}

main.cpp:

#include <QtGui/QApplication>
#include "Widget.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

参考资料:

  1. QT实验分析教程

Qt模型视图中的委托相关推荐

  1. Qt 模型视图框架解读之模型

    Qt 模型视图框架 前后阅读的好几遍,要不是项目中需要处理一些相对比较多的数据,这部分内容估计不会去急着去理解. 首先来了解下什么是模型和视图框架吧: 一般地:MVC 设计模式包括三个元素: 表示数据 ...

  2. Qt 模型视图编程之表头设置

    背景 Qt 模型视图编程中模型定义了标准接口对数据进行访问,可根据需求继承对应的抽象模型类来实现自定义的数据模型.一个基本的数据模型至少要实现以下虚函数: ①.rowCount:行数,返回要显示多少行 ...

  3. Qt 模型视图编程的简单实例

    导言: 当遇到一个相对复杂的项目软件的时候,处理的数据量相对较大,这时候从软件设计的角度,一般都会考虑运用模型视图的架构. Qt关于MVC编程组成部分: 大体上,模型.视图架构中众多类可以分为3组:模 ...

  4. Qt模型视图框架:QListView

    一.描述 QListView 将存储在模型中的项目呈现为简单的非分层列表或图标集合.此视图不显示水平或垂直标题. QStandardItemModel * model = new QStandardI ...

  5. Qt - 模型/视图编程(MVC编程自定义模型)

    模型/视图编程 Qt中的模型/视图架构用来实现大量的数据存储.处理及显示.MVC(Model-View-Controller)包括了3个组件:模型(Model)是应用对象,用来表示数据:视图(View ...

  6. QT学习笔记14(Qt模型视图结构)

    一.基础知识 1.MVC设计模式:是一种与用户界面相关的设计模式,通过此模式,可以有效的分离数据和用户界面. MVC包括三个要素: 表示数据的模型(Model):应用程序的对象 表示用户界面的视图(V ...

  7. Qt中的模型视图设计模式

    文章目录 1 初探Qt中的模型视图设计模式 2 模型视图中的索引 3 模型中的数据组织方式初探 1 初探Qt中的模型视图设计模式 模型视图设计模式的核心思想: 模型(数据)与视图(显示)相分离. 模型 ...

  8. 将OSG嵌入QT窗口系统中,实现拖拽界面

    将OSG嵌入QT窗口系统中,实现拖拽界面 一.原理 OSG底层使用的是OpenGL图形系统,QT也增加了对OpenGL的支持,因此,可以通过QT的OpenGL模块,实现将OSG窗口嵌入到QT中,这样可 ...

  9. Qt中模型/视图结构

    8.1 概述 MVC设计模式是起源于Smalltalk的一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包括三个元素:表示数据的模型 (Model).表示用户 ...

最新文章

  1. 静态方法多次调用内存_java虚拟机的内存分析
  2. linux下使用expect+scp+shell实现分布式集群系统安装,升级,部署
  3. 500只产品汪周末齐聚宇宙中心五道口,这里发生了什么?
  4. java springcloud版b2b2c社交电商spring cloud分布式微服务-docker-feign(四)
  5. jsf绑定bean_JSF –渴望的CDI bean
  6. 苹果出来挨打!又一个不配充电器的来了
  7. 通过命令行工具使用阿里云资源编排服务
  8. android 常用输入法,[转载]Android 系统输入法的调用
  9. python爬虫下载文件到指定文件夹_python爬虫: 从 指定路径 爬取 文件
  10. ACR122U-A9|ACR1251|ACM1252系列NFC读写器读卡器PCSC Tool测试工具使用步骤说明
  11. Rust搜索服务器、rust快速找服教程
  12. nginx代理出现Provisional headers are shown
  13. 一文读懂反向传播算法原理
  14. Apache反向代理配置
  15. 同样是手写笔,Apple Pencil到底输在了哪里?
  16. iOS开发之利用苹果系统自带地图进行地图开发
  17. 谷歌浏览器扩展程序XDM_设计师的谷歌Chrome浏览器拓展程序推荐!Design Service Center...
  18. vscode代码索引_VS Code:自定义代码片断(Snippets)
  19. 密码学归约证明——哈希签名范式的安全性
  20. 概率论的一些基本概念

热门文章

  1. python2 x与python3 x_python2.x 与 python3.x的不同
  2. STM32 ADC 同步规则模式 ADC1与ADC2同用一个DMA
  3. 【需求】手机无线投屏到电视需求整理,Miracast无线投屏功能应用及需求
  4. [Android工具]更新安卓百度云盘百度网盘资源搜索工具,安卓网盘搜索软件
  5. 【测试】用示波器抓取红外遥控器NEC信号
  6. 【DIY】可能是最简单便宜的DIY温湿度计,arduino温湿度计
  7. 考前自学系列·计算机组成原理·补码定点加减运算和溢出判断,浮点数的加减运算,原码的乘法
  8. 售后服务成OA品牌竞争重要因素
  9. 你能用微信小程序打开小程序了【附开发方法】
  10. Open-E DSS V7 应用系列之三 Web管理简介