(四十一)视图中的委托

来源:互联网 发布:linux sigpipe 编辑:程序博客网 时间:2024/06/06 11:42

视图与委托

1、  委托是视图的一部分,需要承担数据显示的部分工作

2、  视图负责确定数据的显示方式(列表、表格、树形)

3、  委托负责具体数据项的显示和编辑(数据项值、编辑器)

4、  视图和委托共同完成数据显示功能和数据编辑功能

 

/*

1、在视图setItemDelegate()时,将参数设置为NULL,即取消视图的委托,运行时,仍能看出视图是以怎样的方式显示数据的(能分别是列表、表格、还是树形),甚至能显示出模型的HeaderLabel,但是不能显示具体的数据项,双击也不会出现编辑框,也就是不能编辑数据项。

2、注释掉委托的paint()成员函数的函数体,运行时,现象与1类似,不同的地方在于,虽不能显示具体数据项,但能显示数据项的外围线条,双击也会出现编辑框,并能编辑数据项

*/

 

改变视图中数据项的显示方式

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

1、 重写paint ()成员函数

2、  在paint ()中自定义数据项显示方式

3、  重写editorEvent()成员函数

4、  在editorEvent()中处理交互事件

 

定义数据项显示方式

//伪代码

void CustomizedItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)const{    if( /* 数据项满足自定义显示条件 */)    {        //1. 根据索引参数获取模型中的数据               //2. 定义绘制参数对象        QStyleOptionXXXX xxxxOption;               //3. 设置具体参数到xxxxOption对象               //4. 根据参数对象xxxxOption绘制数据显示方式       QApplication::style()->drawControl(QStyle::CE_XXXX,                                           &xxxxOption,                                          painter);           }    else    {        QItemDelegate::paint(painter, option,index);    }}


 

处理交互事件

//伪代码

boolCustomizedItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,const QStyleOptionViewItem &option, const QModelIndex &index)    {   bool ret = true;           if( /* 数据项满足自定义显示条件 */)            {                          //1.转换事件event类型              if( /* 发生事件的具体类型满足并在option内*/)       {                          //2.根据index去模型中取数据                    //3.修改数据并返回模型        }    }   else     {       ret = QItemDelegate::editorEvent(event, model, option, index);    }    return ret;                 //表明已经处理}


一、

//CustomizedItemDelegate.h

 

#ifndef CUSTOMIZEDITEMDELEGATE_H#define CUSTOMIZEDITEMDELEGATE_H #include <QItemDelegate>#include <QModelIndex> class CustomizedItemDelegate : publicQItemDelegate{   Q_OBJECT 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, constQModelIndex &index) const;   void paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex &index) const;   bool editorEvent(QEvent *event, QAbstractItemModel *model, constQStyleOptionViewItem &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, constQStyleOptionViewItem &option, const QModelIndex &index) const{   QWidget* ret = NULL;         //要修数据类型为BOOL类型的数据项编辑器的默认显示方式,因此此处就不创建对应的编辑器,而是在重写的paint()函数处理BOOL   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;} voidCustomizedItemDelegate::updateEditorGeometry(QWidget *editor, constQStyleOptionViewItem &option, const QModelIndex &index) const{   editor->setGeometry(option.rect);} voidCustomizedItemDelegate::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);    }} voidCustomizedItemDelegate::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;        //QStyleOptionButton类对象用于描述button的属性信息        checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off;      //根据data值设置是否选中       checkBoxStyle.state |= QStyle::State_Enabled;      //可操作属性       checkBoxStyle.rect = option.rect;   //option保存当前数据项在视图中的外观信息,这里是使用数据项大小       checkBoxStyle.rect.setX(option.rect.x() + option.rect.width() / 2 - 6);   //设置rect的x坐标        QApplication::style()->drawControl(QStyle::CE_CheckBox,&checkBoxStyle, painter); //调用构造函数style()得到保存有跟操作系统风格相关的对象,再绘制控件,绘制对象时CheckBox    }   else    {       QItemDelegate::paint(painter, option, index);    }}//处理交互事件bool CustomizedItemDelegate::editorEvent(QEvent*event, QAbstractItemModel *model, const QStyleOptionViewItem &option,const QModelIndex &index)    {   bool ret = true;         //index就是代表的正在被操作的数据项的   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_OBJECT      QTableView 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();}


 

//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_OBJECT      QTableView 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);                  //每隔500秒发送一次timeout} 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(){   }


 

 

//CustomizedItemDelegate.h

 

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


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


 

 

 

 

 

 

 

 

 

 

 

 

 

0 0
原创粉丝点击