Qt模型视图中的委托
文章目录
- 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 自定义委托
首先来看一下委托的本质:
- 为视图提供数据编辑的上下文环境。
- 产生界面元素的工厂类。
- 能够使用和设置模型中的数据。
问题:如何自定一个委托类?
自定义委托时需要重写的函数:
- 重写creatorEditor成员函数:
- 重写updateEditorGeometry成员函数。
- 重写setEditorData成员函数。
- 重写setModelData成员函数。
- 重写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:自定义视图显示方式
思考:如何改变视图默认的数据显示方式?
自定义委托的默认数据显示方式:
- 重写paint成员函数。
- 在paint中自定义数据显示方式。
- 重写editorEvent成员函数。
- 在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从纯文本的显示方式改变为进度条+文本显示的方式;可以直观的让用户感受到当前的任务进度。
解决方案:
- 自定义新的委托类。
- 在paint成员函数中绘制进度条显示方式。
- 在editorEvent成员函数中禁止数据编辑操作。
在paint成员函数中绘制进度条显示:
在editorEvent成员函数中禁止数据编辑操作:
任务进度模拟:
- 定义计时器用于模拟任务进度。
- 定义计时器槽函数void timerTimeOut()。
- 在槽函数中修改模型中的数据。
实例扩展:在实际工程项目中,可以使用后台线程根据实际的任务情况更新模型中的数据,从而更新数据的界面显示。
总结一下自定义视图数据显示的方法:
实例代码如下:
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();
}
参考资料:
- QT实验分析教程
Qt模型视图中的委托相关推荐
- Qt 模型视图框架解读之模型
Qt 模型视图框架 前后阅读的好几遍,要不是项目中需要处理一些相对比较多的数据,这部分内容估计不会去急着去理解. 首先来了解下什么是模型和视图框架吧: 一般地:MVC 设计模式包括三个元素: 表示数据 ...
- Qt 模型视图编程之表头设置
背景 Qt 模型视图编程中模型定义了标准接口对数据进行访问,可根据需求继承对应的抽象模型类来实现自定义的数据模型.一个基本的数据模型至少要实现以下虚函数: ①.rowCount:行数,返回要显示多少行 ...
- Qt 模型视图编程的简单实例
导言: 当遇到一个相对复杂的项目软件的时候,处理的数据量相对较大,这时候从软件设计的角度,一般都会考虑运用模型视图的架构. Qt关于MVC编程组成部分: 大体上,模型.视图架构中众多类可以分为3组:模 ...
- Qt模型视图框架:QListView
一.描述 QListView 将存储在模型中的项目呈现为简单的非分层列表或图标集合.此视图不显示水平或垂直标题. QStandardItemModel * model = new QStandardI ...
- Qt - 模型/视图编程(MVC编程自定义模型)
模型/视图编程 Qt中的模型/视图架构用来实现大量的数据存储.处理及显示.MVC(Model-View-Controller)包括了3个组件:模型(Model)是应用对象,用来表示数据:视图(View ...
- QT学习笔记14(Qt模型视图结构)
一.基础知识 1.MVC设计模式:是一种与用户界面相关的设计模式,通过此模式,可以有效的分离数据和用户界面. MVC包括三个要素: 表示数据的模型(Model):应用程序的对象 表示用户界面的视图(V ...
- Qt中的模型视图设计模式
文章目录 1 初探Qt中的模型视图设计模式 2 模型视图中的索引 3 模型中的数据组织方式初探 1 初探Qt中的模型视图设计模式 模型视图设计模式的核心思想: 模型(数据)与视图(显示)相分离. 模型 ...
- 将OSG嵌入QT窗口系统中,实现拖拽界面
将OSG嵌入QT窗口系统中,实现拖拽界面 一.原理 OSG底层使用的是OpenGL图形系统,QT也增加了对OpenGL的支持,因此,可以通过QT的OpenGL模块,实现将OSG窗口嵌入到QT中,这样可 ...
- Qt中模型/视图结构
8.1 概述 MVC设计模式是起源于Smalltalk的一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包括三个元素:表示数据的模型 (Model).表示用户 ...
最新文章
- 静态方法多次调用内存_java虚拟机的内存分析
- linux下使用expect+scp+shell实现分布式集群系统安装,升级,部署
- 500只产品汪周末齐聚宇宙中心五道口,这里发生了什么?
- java springcloud版b2b2c社交电商spring cloud分布式微服务-docker-feign(四)
- jsf绑定bean_JSF –渴望的CDI bean
- 苹果出来挨打!又一个不配充电器的来了
- 通过命令行工具使用阿里云资源编排服务
- android 常用输入法,[转载]Android 系统输入法的调用
- python爬虫下载文件到指定文件夹_python爬虫: 从 指定路径 爬取 文件
- ACR122U-A9|ACR1251|ACM1252系列NFC读写器读卡器PCSC Tool测试工具使用步骤说明
- Rust搜索服务器、rust快速找服教程
- nginx代理出现Provisional headers are shown
- 一文读懂反向传播算法原理
- Apache反向代理配置
- 同样是手写笔,Apple Pencil到底输在了哪里?
- iOS开发之利用苹果系统自带地图进行地图开发
- 谷歌浏览器扩展程序XDM_设计师的谷歌Chrome浏览器拓展程序推荐!Design Service Center...
- vscode代码索引_VS Code:自定义代码片断(Snippets)
- 密码学归约证明——哈希签名范式的安全性
- 概率论的一些基本概念
热门文章
- python2 x与python3 x_python2.x 与 python3.x的不同
- STM32 ADC 同步规则模式 ADC1与ADC2同用一个DMA
- 【需求】手机无线投屏到电视需求整理,Miracast无线投屏功能应用及需求
- [Android工具]更新安卓百度云盘百度网盘资源搜索工具,安卓网盘搜索软件
- 【测试】用示波器抓取红外遥控器NEC信号
- 【DIY】可能是最简单便宜的DIY温湿度计,arduino温湿度计
- 考前自学系列·计算机组成原理·补码定点加减运算和溢出判断,浮点数的加减运算,原码的乘法
- 售后服务成OA品牌竞争重要因素
- 你能用微信小程序打开小程序了【附开发方法】
- Open-E DSS V7 应用系列之三 Web管理简介