Qt之QHeaderView添加复选框
2016-03-01 14:53
555 查看
简述
前面分享了QTableView中如何添加复选框。本节主要介绍QTableView中的表头-QHeaderView添加复选框的功能,下面以水平表头为例,垂直表头类似!简述
效果
QHeaderView
源码
接口说明
QAbstractTableModel
源码
接口说明
使用
效果
QHeaderView
源码
TableHeaderView::TableHeaderView(Qt::Orientation orientation, QWidget *parent) : QHeaderView(orientation, parent), m_bPressed(false), m_bChecked(false), m_bTristate(false), m_bNoChange(false), m_bMoving(false) { // setStretchLastSection(true); setHighlightSections(false); setMouseTracking(true); // 响应鼠标 setSectionsClickable(true); } // 槽函数,用于更新复选框状态 void TableHeaderView::onStateChanged(int state) { if (state == Qt::PartiallyChecked) { m_bTristate = true; m_bNoChange = true; } else { m_bNoChange = false; } m_bChecked = (state != Qt::Unchecked); update(); } // 绘制复选框 void TableHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const { painter->save(); QHeaderView::paintSection(painter, rect, logicalIndex); painter->restore(); if (logicalIndex == CHECK_BOX_COLUMN) { QStyleOptionButton option; option.initFrom(this); if (m_bChecked) option.state |= QStyle::State_Sunken; if (m_bTristate && m_bNoChange) option.state |= QStyle::State_NoChange; else option.state |= m_bChecked ? QStyle::State_On : QStyle::State_Off; if (testAttribute(Qt::WA_Hover) && underMouse()) { if (m_bMoving) option.state |= QStyle::State_MouseOver; else option.state &= ~QStyle::State_MouseOver; } QCheckBox checkBox; option.iconSize = QSize(20, 20); option.rect = rect; style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter, &checkBox); //style()->drawItemPixmap(painter, rect, Qt::AlignCenter, QPixmap(":/images/checkBoxChecked")); //style()->drawControl(QStyle::CE_CheckBox, &option, painter, this); } } // 鼠标按下表头 void TableHeaderView::mousePressEvent(QMouseEvent *event) { int nColumn = logicalIndexAt(event->pos()); if ((event->buttons() & Qt::LeftButton) && (nColumn == CHECK_BOX_COLUMN)) { m_bPressed = true; } else { QHeaderView::mousePressEvent(event); } } // 鼠标从表头释放,发送信号,更新model数据 void TableHeaderView::mouseReleaseEvent(QMouseEvent *event) { if (m_bPressed) { if (m_bTristate && m_bNoChange) { m_bChecked = true; m_bNoChange = false; } else { m_bChecked = !m_bChecked; } update(); Qt::CheckState state = m_bChecked ? Qt::Checked : Qt::Unchecked; emit stateChanged(state); } else { QHeaderView::mouseReleaseEvent(event); } m_bPressed = false; } // 鼠标滑过、离开,更新复选框状态 bool TableHeaderView::event(QEvent *event) { if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) { QMouseEvent *pEvent = static_cast<QMouseEvent *>(event); int nColumn = logicalIndexAt(pEvent->x()); if (nColumn == CHECK_BOX_COLUMN) { m_bMoving = (event->type() == QEvent::Enter); update(); return true; } } return QHeaderView::event(event); }
接口说明
onStateChanged槽函数,与model关联,当model的数据发生变化时,表头复选中状态也随之变化。
paintSection
绘制部分,主要用于绘制复选框,主要设置QStyleOptionButton的状态,然后通过QStyle的drawPrimitive绘制样式。
mousePressEvent
鼠标按下表头,设置被按下的标志为true。
mouseReleaseEvent
鼠标从表头释放,发送信号,更新model数据。
event
鼠标滑过、离开,更新复选框状态。
QAbstractTableModel
源码
源码过多,这里只贴更改部分及新增部分,其它部分请参考:Qt之QTableView添加复选框(QAbstractItemDelegate)// 设置表格项数据 bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid()) return false; int nColumn = index.column(); FileRecord record = m_recordList.at(index.row()); switch (role) { case Qt::DisplayRole: { if (nColumn == File_PATH_COLUMN) { record.strFilePath = value.toString(); m_recordList.replace(index.row(), record); emit dataChanged(index, index); return true; } } case Qt::CheckStateRole: case Qt::UserRole: { if (nColumn == CHECK_BOX_COLUMN) { record.bChecked = value.toBool(); m_recordList.replace(index.row(), record); emit dataChanged(index, index); if (role == Qt::UserRole) onStateChanged(); return true; } } default: return false; } return false; } // 复选状态改变,通知表头更新复选状态 void TableModel::onStateChanged() { Qt::CheckState state = Qt::Unchecked; int nCount = m_recordList.count(); int nSelectedCount = 0; FileRecord record; for (int i = 0; i < nCount; ++i) { record = m_recordList.at(i); if (record.bChecked) ++nSelectedCount; } if (nSelectedCount >= nCount) { state = Qt::Checked; } else if (nSelectedCount > 0) { state = Qt::PartiallyChecked; } emit stateChanged(state); } // 接收表头复选状态更新变化,修改表格复选状态 void TableModel::onStateChanged(int state) { QModelIndex index; for (int i = 0; i < rowCount(); ++i) { index = this->index(i, CHECK_BOX_COLUMN); setData(index, state == Qt::Checked, Qt::CheckStateRole); } }
接口说明
setData设置表格项数据,关键代码:当role为Qt::UserRole时候,会调用onStateChanged()函数,来更新表头!
onStateChanged
复选状态改变,通知表头更新复选状态。
onStateChanged(int state)
槽函数,接收表头复选状态更新变化,修改表格复选状态。
使用
这时,就需要将header与model的信号与槽关联起来,更新复选框状态了!QTableView *pTableView = new QTableView(this); TableModel *pModel = new TableModel(this); TableHeaderView *pHeader = new TableHeaderView(Qt::Horizontal, this); CheckBoxDelegate *pDelegate = new CheckBoxDelegate(this); pTableView->setHorizontalHeader(pHeader); pTableView->setModel(pModel); pTableView->setItemDelegate(pDelegate); connect(pModel, SIGNAL(stateChanged(int)), pHeader, SLOT(onStateChanged(int))); connect(pHeader, SIGNAL(stateChanged(int)), pModel, SLOT(onStateChanged(int)));
相关文章推荐
- QT学习 第一章:基本对话框
- 使用Shiboken为C++和Qt库创建Python绑定
- Qt 5.6更新至RC版,最终版本近在咫尺
- Qt定时器和随机数详解
- Qt实现图片移动实例(图文教程)
- Qt for Android开发实例教程
- QModelIndex/Role/Model介紹<二>
- 基于PyQt5的快速开发框架QFramer
- OSX下安装PyQt
- ok6410开发板移植DirectFB手记
- 【笔记】给Qt内嵌一个Chrome吧
- 【算法】最短路径之A*搜索
- qt入门必备
- 在 Qt4 中使用 C++11
- Hello Word ~ v0.2.2 背单词软件发布 -- By WHYPRO
- ubuntu下opencv和qt的安装配置
- linux下opengl的安装(with qt)
- qt 学习小节
- QT编译时Cannot find -lGL
- QT的命名风格