C++ QTableView中标题单元格中的复选框
我想要一个简单的列标题,带有一个复选框,用于选择/取消选择QTableView中的所有行。单击标题中的复选框会导致选择或取消选择所有行 当我想在表格单元格中添加复选框时,我必须返回数据(..)中所需模型索引的Qt::CheckStateRole的检查状态,如下所示。这是预期的工作C++ QTableView中标题单元格中的复选框,c++,qt,qt4,C++,Qt,Qt4,我想要一个简单的列标题,带有一个复选框,用于选择/取消选择QTableView中的所有行。单击标题中的复选框会导致选择或取消选择所有行 当我想在表格单元格中添加复选框时,我必须返回数据(..)中所需模型索引的Qt::CheckStateRole的检查状态,如下所示。这是预期的工作 QVariant MyModel::data( const QModelIndex & rIndex, int iRole) const { ... if (iRole == Qt::Qt:
QVariant MyModel::data( const QModelIndex & rIndex, int iRole) const
{
...
if (iRole == Qt::Qt::CheckStateRole)
{
return checkstate;
}
}
但是,当我想在标题单元格中添加复选框时,上述方法不起作用。这是我的示例代码
QVariant MyModel::headerData( int iSection, Qt::Orientation eOrientation, int iRole) const
{
...
if (iRole == Qt::CheckStateRole)
{
return checkstate;
}
}
与data()函数一样,QTableView不会使用Qt::CheckStateRole在我的模型中调用headerData()函数
为什么会有这种行为?如何仅通过修改自定义表格模型在标题单元格中插入复选框
(我不想为此创建自定义QTableView或QHeaderView)您不能这样做-默认情况下,Qt不支持标题中的复选框。您可以使用自定义的
QHeaderView
阅读更多信息及其实现。这里有一点修改/修复(复选框显示为禁用,重绘不起作用)代码来自接受答案中的链接
h
.cpp
用法
我很惊讶这样一个黑客解决方案被推荐和使用 首先:检查状态应存储在模型中。所有工具都已存在
bool MyModel::setHeaderData(int index, Qt::Orientation orient, const QVariant& val, int role)
{
if(Qt::Vertical != orient)
return Base::setHeaderData(index, orient, val, role);
storeCheckState(index, val);
emit headerDataChanged(orient, index, index);
return true;
}
QVariant MyModel::headerData(int index, Qt::Orientation o, int role) const
{
if(Qt::Vertical != orient)
return Base::headerData(index, o, role);
switch(role)
{
...
case Qt::CheckStateRole:
return fetchCheckState(index);
}
return Base::headerData(index, o, role);
}
Second:我们只需处理标题上的点击信号即可切换选中状态
connect(header, &QHeaderView::sectionClicked, receiver
, [receiver](int sec)
{
const auto index = logicalIndex(sec);
model()->setHeaderData(index
, Qt::Vertical
, Qt::CheckState(model()->headerData(index, Qt::Vertical, Qt::CheckStateRole).toUInt()) != Qt::Checked ? Qt::Checked : Qt::Unchecked
, Qt::CheckStateRole);
});
第三名:
在这一点上,我们有全功能的检查行为,唯一缺少的部分是可视化。最明智的方法是再次使用模型,利用Qt::DecorationRole
。下面是一个虚拟实现:
QVariant MyModel::headerData(int index, Qt::Orientation o, int role) const
{
if(Qt::Vertical != orient)
return Base::headerData(index, o, role);
switch(role)
{
case Qt::DecorationRole:
{
QPixmap p{12,12};
p.fill(Qt::CheckState(headerData(index, o, Qt::CheckStateRole).toUInt()) ? Qt::green : Qt::red);
return p;
}
break;
...
}
return Base::headerData(index, o, role);
}
当然,可以使用样式化绘图在那里绘制一个真正的复选框
注意,此解决方案不需要子分类和自定义小部件
此外,检查状态与视图/UI分离。唯一的缺点是视觉效果是由模型处理的,但这是可选的-可以使用任何方式绘制检查状态,包括备选答案中的检查状态 如果您有时间,请从第三方资源复制或重新实现代码。只有链接的答案的问题是链接到站点的答案经常会消失,而答案变得毫无用处
bool MyModel::setHeaderData(int index, Qt::Orientation orient, const QVariant& val, int role)
{
if(Qt::Vertical != orient)
return Base::setHeaderData(index, orient, val, role);
storeCheckState(index, val);
emit headerDataChanged(orient, index, index);
return true;
}
QVariant MyModel::headerData(int index, Qt::Orientation o, int role) const
{
if(Qt::Vertical != orient)
return Base::headerData(index, o, role);
switch(role)
{
...
case Qt::CheckStateRole:
return fetchCheckState(index);
}
return Base::headerData(index, o, role);
}
connect(header, &QHeaderView::sectionClicked, receiver
, [receiver](int sec)
{
const auto index = logicalIndex(sec);
model()->setHeaderData(index
, Qt::Vertical
, Qt::CheckState(model()->headerData(index, Qt::Vertical, Qt::CheckStateRole).toUInt()) != Qt::Checked ? Qt::Checked : Qt::Unchecked
, Qt::CheckStateRole);
});
QVariant MyModel::headerData(int index, Qt::Orientation o, int role) const
{
if(Qt::Vertical != orient)
return Base::headerData(index, o, role);
switch(role)
{
case Qt::DecorationRole:
{
QPixmap p{12,12};
p.fill(Qt::CheckState(headerData(index, o, Qt::CheckStateRole).toUInt()) ? Qt::green : Qt::red);
return p;
}
break;
...
}
return Base::headerData(index, o, role);
}