Qt引入了模型/视图结构用于完成数据与界面的分离,即InterView框架。InterView框架把视图和控制器部件结合在一起,使得框架更为简洁。
Qt的模型/视图结构分为三部分:模型(Model)、视图(View)和代理(Delegate)。模型与数据源通信,并为其他部件提供接口;视图从模型中获得用来引用数据条目的模型索引。在视图中,代理负责绘制数据条目,当编辑条目时,代理和模型直接进行通信。模型/视图/代理之间通过信号和槽进行通信。
本文主要展示模型数据加载、视图显示和代理操作三部分功能。示例显示:
![请添加图片描述](https://img-blog.csdnimg.cn/direct/4d68b5328011426fa15ad97773e435fa.gif)
1.模型数据加载
QStandardItemModel m_model;
m_model.setRowCount(4);
m_model.setColumnCount(4);
m_model.setHeaderData(0,Qt::Horizontal,QString::fromLocal8Bit("姓名"));
m_model.setHeaderData(1,Qt::Horizontal,QString::fromLocal8Bit("生日"));
m_model.setHeaderData(2,Qt::Horizontal,QString::fromLocal8Bit("职业"));
m_model.setHeaderData(3,Qt::Horizontal,QString::fromLocal8Bit("收入"));
QFile file("../SRC/doc/test.txt");
if(file.open(QFile::ReadOnly|QFile::Text))
{
QTextStream stream(&file);
QString line;
m_model.removeRows(0,m_model.rowCount(QModelIndex()),QModelIndex());
int row = 0;
do
{
line = stream.readLine();
if(!line.isEmpty())
{
m_model.insertRows(row,1,QModelIndex());
QStringList pieces = line.split(",",QString::SkipEmptyParts);
m_model.setData(m_model.index(row,0,QModelIndex()),pieces.value(0));
m_model.setData(m_model.index(row,1,QModelIndex()),pieces.value(1));
m_model.setData(m_model.index(row,2,QModelIndex()),pieces.value(2));
m_model.setData(m_model.index(row,3,QModelIndex()),pieces.value(3));
row++;
}
}while(!line.isEmpty());
file.close();
}
2.视图显示
ui->tableView->setModel(&m_model);
QHeaderView* headerView = ui->tableView->horizontalHeader();
headerView->setSectionResizeMode(QHeaderView::Interactive);
3.代理操作
DateDelegate m_dateDelegate;
ComboDelegate m_comboDelegate;
SpinDelegate m_spinDelegate;
ui->tableView->setItemDelegateForColumn(1,&m_dateDelegate);
ui->tableView->setItemDelegateForColumn(2,&m_comboDelegate);
ui->tableView->setItemDelegateForColumn(3,&m_spinDelegate);
3.1时间日历代理
构建项目DataDelegate,使用手动的方式实现对生日的录入编辑。
class DateDelegate:public QItemDelegate
{
Q_OBJECT
public:
DateDelegate(QObject *parent = nullptr);
//完成创建控件的工作
QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index)const;
//设置控件显示的数据,将Model中的数据更新至Delegate中
void setEditorData(QWidget *editor,const QModelIndex &index)const;
void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index)const;
void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index)const;
};
DateDelegate::DateDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *DateDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//新建QDateTimeEdit对象
QDateTimeEdit *editor = new QDateTimeEdit(parent);
editor->setDisplayFormat("yyyy-MM-dd");
editor->setCalendarPopup(true);//以Popup的方式显示日历
editor->installEventFilter(const_cast<DateDelegate*>(this));//安装事件过滤器,使DateDelegate能够捕获QDateTimeEdit对象
return editor;
}
void DateDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QString dateStr = index.model()->data(index).toString();//获取指定index数据项的数据
QDate date = QDate::fromString(dateStr,Qt::ISODate);//转换QString类型表示的日期数据转换为QDate类型
QDateTimeEdit *edit = static_cast<QDateTimeEdit*>(editor);
edit->setDate(date);
}
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)));//调用setDate()函数将数据更新到Model中
}
void DateDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
3.2下拉框代理
构建项目ComboDelegate,使用手动的方式实现对职业的录入编辑
class ComboDelegate:public QItemDelegate
{
Q_OBJECT
public:
ComboDelegate(QObject *parent = nullptr);
//完成创建控件的工作
QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index)const;
//设置控件显示的数据,将Model中的数据更新至Delegate中
void setEditorData(QWidget *editor,const QModelIndex &index)const;
void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index)const;
void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index)const;
};
ComboDelegate::ComboDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *ComboDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
//创建QComboBox控件
QComboBox *editor = new QComboBox(parent);
editor->addItem("工人");
editor->addItem("农民");
editor->addItem("医生");
editor->addItem("律师");
editor->addItem("军人");
editor->installEventFilter(const_cast<ComboDelegate*>(this));
return editor;
}
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);
}
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);
}
void ComboDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}
3.3输入框代理
构建项目ComboDelegate,使用手动的方式实现对收入的录入编辑。
class SpinDelegate:public QItemDelegate
{
Q_OBJECT
public:
SpinDelegate(QObject *parent = nullptr);
//完成创建控件的工作
QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index)const;
//设置控件显示的数据,将Model中的数据更新至Delegate中
void setEditorData(QWidget *editor,const QModelIndex &index)const;
void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index)const;
void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index)const;
};
SpinDelegate::SpinDelegate(QObject *parent):QItemDelegate(parent)
{
}
QWidget *SpinDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QSpinBox *spinBox = new QSpinBox(parent);
spinBox->setRange(0,10000);
spinBox->installEventFilter(const_cast<SpinDelegate*>(this));
return spinBox;
}
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);
}
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);
}
void SpinDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
editor->setGeometry(option.rect);
}