#include "TableHeaderView.h" #include #include #include #include #ifdef _MSC_VER #pragma execution_character_set("utf-8") #endif #define CHECK_BOX_COLUMN 0 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) { setSectionsClickable(true); // 响应鼠标 } TableHeaderView::~TableHeaderView() { } // 槽函数,用于更新复选框状态 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); } } // 鼠标按下表头 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); updateSection(0); } else { QHeaderView::mouseReleaseEvent(event); } m_bPressed = false; } // 鼠标滑过、离开,更新复选框状态 bool TableHeaderView::event(QEvent *event) { updateSection(0); if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) { QMouseEvent *pEvent = static_cast(event); int nColumn = logicalIndexAt(pEvent->x()); if (nColumn == CHECK_BOX_COLUMN) { m_bMoving = (event->type() == QEvent::Enter); update(); return true; } } return QHeaderView::event(event); } CheckBoxDelegate::CheckBoxDelegate(QObject *parent) :QStyledItemDelegate(parent) { } CheckBoxDelegate::~CheckBoxDelegate() { } // 绘制复选框 void CheckBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionViewItem viewOption(option); initStyleOption(&viewOption, index); if (option.state.testFlag(QStyle::State_HasFocus)) viewOption.state = viewOption.state ^ QStyle::State_HasFocus; QStyledItemDelegate::paint(painter, viewOption, index); if (index.column() == CHECK_BOX_COLUMN ) { bool data = index.model()->data(index, Qt::UserRole).toBool(); QStyleOptionButton checkBoxStyle; checkBoxStyle.state = data ? QStyle::State_On : QStyle::State_Off; checkBoxStyle.state |= QStyle::State_Enabled; checkBoxStyle.iconSize = QSize(20, 20); checkBoxStyle.rect = option.rect; QCheckBox checkBox; checkBoxStyle.iconSize = QSize(20, 20); checkBoxStyle.rect = option.rect; QApplication::style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &checkBoxStyle, painter, &checkBox); checkBox.setEnabled(false); } } // 响应鼠标事件,更新数据 bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { QRect decorationRect = option.rect; QMouseEvent *mouseEvent = static_cast(event); if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos())) { if (index.column() == CHECK_BOX_COLUMN ) { bool data = model->data(index, Qt::UserRole).toBool(); model->setData(index, !data, Qt::UserRole); } } return QStyledItemDelegate::editorEvent(event, model, option, index); }