Bootstrap

QT学习:代理(Delegate)练习

利用Delegate设计表格中控件。
实现步骤如下。
(1)首先,加载表格数据,以便后面的操作。源文件“main.cpp”中的具体代码如下:

#include <QApplication>
#include <QStandardItemModel>
#include <QTableView>
#include <QFile>
#include <QTextStream>
int main(int argc,char *argv[])
{
    QApplication a(argc,argv);
    QStandardItemModel model(4,4);
    QTableView tableView;
    tableView.setModel(&model);
    model.setHeaderData(0,Qt::Horizontal,QObject::tr("姓名"));
    model.setHeaderData(1,Qt::Horizontal,QObject::tr("生日"));
    model.setHeaderData(2,Qt::Horizontal,QObject::tr("职业"));
    model.setHeaderData(3,Qt::Horizontal,QObject::tr("收入"));
    QFile file("test.txt");
    if(file.open(QFile::ReadOnly|QFile::Text))
    {
        QTextStream stream(&file);
        QString line;
        model.removeRows(0,model.rowCount(QModelIndex()),QModelIndex());
        int row =0;
        do{
               line = stream.readLine();
               if(!line.isEmpty())
               {
                   model.insertRows(row,1,QModelIndex());
                   QStringList pieces = line.split(",",QString
                         ::SkipEmptyParts);
                   model.setData(model.index(row,0,QModelIndex()), pieces
                         .value(0));
                   model.setData(model.index(row,1,QModelIndex()), pieces
                         .value(1));
                   model.setData(model.index(row,2,QModelIndex()), pieces
                         .value(2));
                   model.setData(model.index(row,3,QModelIndex()), pieces
                         .value(3));
                   row++;
               }
        }while(!line.isEmpty());
        file.close();
    }
    tableView.setWindowTitle(QObject::tr("Delegate"));
    tableView.show();
    return app.exec();
}

(2)选择“构建”→“构建项目"DateDelegate"”菜单项,首先按照如下图所示的格式编辑本例所用的数据文件“test.txt”,保存在项目build-DateDelegate- Desktop_Qt_5_9_0_MinGW_32bit-Debug目录下。
在这里插入图片描述
然后运行程序,效果如图所示:
在这里插入图片描述
(3)在上图中,使用手动的方式实现对生日的录入编辑。下面使用日历编辑框QDateTimeEdit 控件实现对生日的编辑,用自定义的Delegate来实现。
(4)DateDelegate 继承自QItemDelegate类。头文件“datedelegate.h”中的具体代码如下:

#include <QItemDelegate>
class DateDelegate : public QItemDelegate
{
   Q_OBJECT
public:
    DateDelegate(QObject *parent = 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & option, const QModelIndex &index) const;			//完成创建控件的工作,创建由参数中的QModelIndex对象指定的表项数据的编辑控件,并对控件的内容进行限定。
    void setEditorData(QWidget *editor, const QModelIndex &index) const;	//设置控件显示的数据,将Model中的数据更新至Delegate中,相当于一个初始化工作。
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModel Index &index) const;			  		//将Delegate中对数据的改变更新至Model中
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem & option, const QModelIndex &index) const;			//更新控件区的显示
};

(5)源文件“datedelegate.cpp”中的具体代码如下:

#include "datedelegate.h"
#include <QDateTimeEdit>
DateDelegate::DateDelegate(QObject *parent):QItemDelegate(parent)
{
}

createEditor()函数的具体实现代码如下:

QWidget *DateDelegate::createEditor(QWidget *parent,const QStyleOptionView Item &/*option*/,const QModelIndex &/*index*/) const
{
    QDateTimeEdit *editor = new QDateTimeEdit(parent);		//新建一个QDateTimeEdit对象作为编辑时的输入控件。
    editor->setDisplayFormat("yyyy-MM-dd");			//设置该QDateTimeEdit对象的显示格式为yyyy-MM-dd,此为ISO标准显示方式。
    editor->setCalendarPopup(true);				//设置日历选择的显示以Popup的方式,即下拉菜单方式显示。

    editor->installEventFilter(const_cast<DateDelegate*>(this));		//调用QObject类的installEvent Filter()函数安装事件过滤器,使DateDelegate能够捕获QDateTimeEdit对象的事件。
    return editor;
}

setEditorData()函数的具体代码如下:

void DateDelegate::setEditorData(QWidget *editor,
       const QModelIndex &index) const
{
   QString dateStr= index.model()->data(index).toString();	//获取指定index数据项的数据。调用QModelIndex的model()函数可获得提供index的Model对象,data()函数返回的是一个QVariant对象,toString()函数将它转换为一个QString类型数据。

   QDate date = QDate::fromString(dateStr,Qt::ISODate);	//通过QDate的fromString()函数将以QString类型表示的日期数据转换为QDate类型。Qt::ISODate表示QDate类型的日期是以ISO格式保存的,这样最终转换获得的QDate数据也是ISO格式,使控件显示与表格显示保持一致。

   QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);//将editor转换为QDateTimeEdit对象,以获得编辑控件的对象指针。
   edit->setDate(date);				//设置控件的显示数据
}

setModelData()函数的具体代码如下:

void DateDelegate::setModelData(QWidget *editor,QAbstractItemModel *model, const QModelIndex &index) const
{
    QDateTimeEdit *edit=static_cast<QDateTimeEdit*>(editor);		//通过紧缩转换获得编辑控件的对象指针。
    QDate date = edit->date();						//获得编辑控件中的数据更新。

    model->setData(index,QVariant(date.toString(Qt::ISODate)));		//调用setData()函数将数据修改更新到Model中。
}	

updateEditorGeometry()函数的具体代码如下:

void DateDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

(6)在“main.cpp”文件中添加如下代码:

 #include "datedelegate.h"

在语句tableView.setModel(&model);后面添加如下代码:

DateDelegate dateDelegate;
tableView.setItemDelegateForColumn(1,&dateDelegate);

(7)此时运行程序,双击第1行第2列,将显示如下图所示的日历编辑框控件。
在这里插入图片描述
下面使用下拉列表框QComboBox控件实现对职业类型的输入编辑,使用自定义的Delegate实现。
(1)ComboDelegate继承自QItemDelegate类。
头文件“combodelegate.h”中的具体代码如下:

#include <QItemDelegate>
class ComboDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    ComboDelegate(QObject *parent = 0);
    QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,constQModelIndex	&index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModel Index &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const  QModelIndex &index) const;
};

(2)源文件“combodelegate.cpp”中的具体代码如下:

#include "combodelegate.h"
#include <QComboBox>
ComboDelegate::ComboDelegate(QObject *parent):QItemDelegate(parent)
{
}

createEditor()函数中创建了一个QComboBox控件,并插入可显示的条目,安装事件过滤器。具体代码如下:

QWidget *ComboDelegate::createEditor(QWidget *parent,const QStyleOptionView  Item &/*option*/,const QModelIndex &/*index*/) const
{
    QComboBox *editor = new QComboBox(parent);
    editor->addItem("工人");
    editor->addItem("农民");
    editor->addItem("医生");
    editor->addItem("律师");
    editor->addItem("军人");
    editor->installEventFilter(const_cast<ComboDelegate*>(this));
    return editor;
}

setEditorData()函数中更新了Delegate控件中的数据显示,具体代码如下:

void ComboDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
    QString str =index.model()->data(index).toString();
    QComboBox *box = static_cast<QComboBox*>(editor);
    int i=box->findText(str);
    box->setCurrentIndex(i);
}

setModelData()函数中更新了Model中的数据,具体代码如下:

void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QComboBox *box = static_cast<QComboBox*>(editor);
    QString str = box->currentText();
    model->setData(index,str);
}

updateEditorGeometry()函数的具体代码如下:

void ComboDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect);
}

在“main.cpp”文件中添加以下内容:

 #include "combodelegate.h"

在语句tableView.setModel(&model)的后面添加以下代码:

ComboDelegate comboDelegate;
tableView.setItemDelegateForColumn(2,&comboDelegate);

此时运行程序,双击第1行第3列,显示如图所示的下拉列表:
在这里插入图片描述
下面使用QSpinBox控件实现对收入的输入编辑,调用自定义的Delegate来实现。
SpinDelegate类的实现与ComboDelegate类的实现类似。
(1)头文件“spindelegate.h”中的具体代码如下:

#include <QItemDelegate>
class SpinDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    SpinDelegate(QObject *parent = 0);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex  &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModel Index &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
};

(2)源文件“spindelegate.cpp”中的具体代码如下:

#include "spindelegate.h"
#include <QSpinBox>
SpinDelegate::SpinDelegate(QObject *parent): QItemDelegate(parent)
{
}

createEditor()函数的具体实现代码如下:

QWidget *SpinDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
    QSpinBox *editor = new QSpinBox(parent);
    editor->setRange(0,10000);
    editor->installEventFilter(const_cast<SpinDelegate*>(this));
    return editor;
}

setEditorData()函数的具体实现代码如下:

void SpinDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
    int value =index.model()->data(index).toInt();
    QSpinBox *box = static_cast<QSpinBox*>(editor);
    box->setValue(value);
}

setModelData()函数的具体实现代码如下:

void SpinDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const
{
    QSpinBox *box = static_cast<QSpinBox*>(editor);
    int value = box->value();
    model->setData(index,value);
}

updateEditorGeometry()函数的具体实现代码如下:

void SpinDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect);
}

(3)在“main.cpp”文件中添加代码如下:

  #include "spindelegate.h"

在语句tableView.setModel(&model)的后面添加内容如下:

SpinDelegate spinDelegate;
tableView.setItemDelegateForColumn(3,&spinDelegate);

(4)此时运行程序,双击第1行第4列后的效果如下图所示。
在这里插入图片描述

;