zl程序教程

您现在的位置是:首页 >  工具

当前栏目

Qt之QHeaderView添加复选框

Qt 添加 复选框
2023-09-14 08:56:50 时间

这里写图片描述

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;

 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)));

C/C++ Qt ListWidget 列表框组件应用 ListWidget列表框组件,该组件与TreeWidget有些相似,区别在于TreeWidget可以实现嵌套以及多字段结构,而ListWidget组件则只能实现单字段结构,ListWidget组件常用于显示单条记录,例如只显示IP地址,用户名等数据,如下笔记是本人在开发中经常用到的一些基本操作技巧,包括列表框组件的基本操作方法。