利用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列后的效果如下图所示。