Qt-Model/View综合示例
相关类简介
Qt和Model/View模式相关的类比较多, 但一般存在继承关系, 按model(模型), view(视图), delegate(委托)划分为如下几种:
类型 | 类名 | 简介 | 父类 |
---|---|---|---|
model |
QAbstractItemModel | (抽象类)常用的Model的基类 | QObject |
QStandardItemModel | 通用model可以实现以下任意类型的功能 | QAbstractItemModel | |
QAbstractTableModel | (抽象类)缺省为二维 主要为 QTableView提供数据 |
QAbstractItemModel | |
QAbstractListModel | (抽象类)缺省为一维, 单列数据结构(其实现对应QML中的ListModel) 其实现常用于为QListView提供数据, 或为QML中Repeater等提供数据 子类: QStringListModel |
QAbstractItemModel | |
QStringListModel | 用于处理字符串列表的数据模型 常用于为QListView提供数据 |
QAbstractListModel | |
QFileSystemModel | 类似文件结构(目录树)的model 常用于为QTreeView提供数据 |
QAbstractItemModel | |
QDirModel | 目录结构, 为QTreeView提供数据 | QAbstractItemModel | |
... | |||
view |
QAbstractItemView | (抽象类)派生关系: QWidget->QFrame->QAbstractScrollArea | QAbstractScrollArea |
QListView | 单方向(一维)列表控件 | QAbstractItemView | |
QTableView | 平面(二维)列表控件 构建方式: 用setModel绑定到数据源构建, 单元格一般为文本 其它特性: 支持绑定QSqlTableModel |
QAbstractItemView | |
QTableWidget | 同上, 但单元格得到了扩展, 不能使用setModel绑定 构建方式: 不能调用setModel绑定数据源, 只能使用QTableWidgetItem 进行单元格构建, 单元格中可同时放入文本和控件 |
QTableView | |
QTreeView | 树形结构控件 | QAbstractItemView | |
... | |||
delegate |
QAbstractItemDelegate | (抽象类)委托的基类 | QObject |
QItemDelegate | 自定义绘制 | QAbstractItemDelegate | |
QStyledItemDelegate | (>Qt 4.4版本)默认委托, 加载当前默认style绘制, 一般使用这个类较多. | QAbstractItemDelegate | |
其他 | QItemSelectionModel | 用于保存当前model被选中的部分: QItemSelectionModel* selections = m_tableView->selectionModel(); 主要方法: QModelIndexList selectedIndexes();//获取当前选择了多少item QModelIndexList selectedRows(0);//获取当前(第0列)选择了多少行 |
QObject |
QHeaderView | QTableView的表头, 有两个, 一个横向, 一个纵向, 当我们想实现自定义的 表头时, 需要继承该类实现自定义部分, 如: 常见场景是在横向表头的第一 列加一个全选框. |
QAbstractItemView |
类举例详细介绍
以QAbstractTableModel, QTableView, QStyledItemDelegate举例
QAbstractTableModel
必须实现的虚函数
- rowCount 返回表格多少行
- columnCount 返回表格多少列
- data 返回单元格数据(参数: 单元格索引, 单元格角色(显示, tips, 编辑等), 返回值: 该单元格对应角色的内容)
其它常用接口
-
setData 更新数据
-
sort 排序
-
flags 返回item的标志项, 常用来设置表格是否可选, 是否可以点击复选框
//设置表格可点击复选框 Qt::ItemFlags flags(const QModelIndex &index) const { if (!index.isValid()) return QAbstractItemModel::flags(index); Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if (index.column() == 0) //设置第一列能复选 flags |= Qt::ItemIsUserCheckable; return flags; }
QTableView
必用接口
- setModel(QAbstractItemModel *model); //设置数据源
常用接口
-
//resizeRowsToContents();//设置自动行高, model中数据量多时设置该选项会严重影响速度
-
resizeColumnsToContents();//设置自动列宽, 一般在setModel后设置才会生效. 速度较快.
-
setWordWrap(false); //取消自动换行
-
setTextElideMode(Qt::ElideNone); //超出文本不显示省略号
-
setItemDelegate(QAbstractItemDelegate *delegate) //设置委托/代理delegate, 比如使用QStyledItemDelegate实现的自定义delegate, 不设置此项的话, 默认使用QStyledItemDelegate
-
setEditTriggers(QAbstractItemView::AllEditTriggers); //禁用所有情况下的单元格编辑
-
setContextMenuPolicy(Qt::CustomContextMenu); //Item的鼠标右键设置为发送QWidget::customContextMenuRequested()信号
-
horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); //表头的鼠标右键设置为发送QWidget::customContextMenuRequested()信号
-
//setSelectionMode(QAbstractItemView::ContiguousSelection);//拖动或按shift或ctrl可以选中多行 setSelectionMode(QAbstractItemView::ExtendedSelection); //拖动或按shift能选中多行, 按ctrl可以切换单条item是否选中
-
QItemSelectionModel* selections = selectionModel();//获取当前model选择的部分
QModelIndexList selected = selections->selectedIndexes();//获取当前选择了多少item
QModelIndexList selected = selections->selectedRows(0);//返回当前选择了多少行
-
setHorizontalHeader(new MyHorizontalHeaderView(Qt::Horizontal, this)); //表头设置为自定义表头, MyHorizontalHeaderView继承自QHeaderView
-
horizontalHeader()->setSectionResizeMode(0,QHeaderView::Fixed); //设置第一列不能改变列宽
- QHeaderView::Interactive :0 用户可设置,也可被程序设置成默认大小
- QHeaderView::Fixed :2 用户不可更改列宽
- QHeaderView::Stretch :1 根据空间,自动改变列宽,用户与程序不能改变列宽
- QHeaderView::ResizeToContents:3 根据内容改变列宽,用户与程序不能改变列宽
自定义QTableView的一些功能实现代码
我们常常需要给QTableView加上, 表头点击排序, 表头右键菜单, Item项右键菜单等功能:
QStyledItemDelegate
常用接口和信号
- createEditor 创建一个QWidget(名为editor)用于编辑数据, 返回QWidget*
- setEditorData 是将model中当前有的数据加载到上面创建的QWidget(editor)上, 自己实现从model中取数据, 和(setValue)放到editor上
- updateEditorGeometry 设置editor显示到一定位置, 并设定其大小, 使这个editor看起来像是单元格的一部分一样, 用到option.rect
- setModelData 将editor上的数据保存到model中
- closeEditor 信号: 表示用户已完成对数据的编辑,可以销毁editor了
- commitData() 信号: 必须在完成编辑数据之后, 发送该信号, 将会把新数据写回model
- paint() 和 sizeHint() 如果需要特殊风格绘制单元项中内容, 需要重载这两个函数.
QItemSelectionModel
QHeaderView
常用接口
- setSectionsClickable(true); //设置表头响应单击
- setHighlightSections(true); //设置表头有高亮效果
实现自定义绘制部分表头内容
void paintSection(QPainter * painter, const QRect & rect, int logicalIndex ) const
{
if (logicalIndex != 0)
QHeaderView::paintSection(painter, rect, logicalIndex); //这里只绘制第一列, 故其余列采用系统绘制.
else
{
// qDebug() << "#HorizontalHeaderView# paintSection() " << rect;
QStyleOptionViewItem opt; //定义一个小部件对象
opt.initFrom(this);
opt.rect = rect;
if (m_isCheckAll)
opt.state |= QStyle::State_On;
else
opt.state |= QStyle::State_Off;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, painter);
}
}