我QProduitCartoHeaderView
在继承自QHeaderView
.
在我的标题中,我有一个复选框,用于选中/取消选中同一列中所有数据行的所有复选框。
目前,当我单击第一列标题单元格中的任意位置(带有复选框的单元格)时,它会检查标题复选框。
我想要做的是仅在我准确单击复选框并且单击外部(但仍在单元格内)以对第一列进行排序时才选中该复选框。
我试图调整复选框矩形的大小(如QProduitCartoHeaderView::paintSection()
下面的片段所示),但是当我单击单元格中的任意位置(而不是复选框)时,我仍然会检查它。
注意:我已经设法使代码进行排序和检查。我不能做的是检查我是单击复选框还是单击单元格内的复选框外部。
这是我的自定义标题的片段:
- QProduitCartoHeaderView.h
#ifndef QPRODUITCARTOHEADERVIEW_H
#define QPRODUITCARTOHEADERVIEW_H
#include <QWidget>
#include <QPainter>
#include <QHeaderView>
#include <QMessageBox>
class QProduitCartoHeaderView :public QHeaderView
{
Q_OBJECT
public:
QProduitCartoHeaderView(QWidget * parent = 0);
~QProduitCartoHeaderView();
void on_sectionClicked(int logicalIndex);
bool all_first_columns_checked(int logicalIndex = 0);
bool all_first_columns_unchecked(int logicalIndex=0);
void setIsOn(bool val);
void setPasTousLesMeme(bool val);
protected:
virtual void paintSection(QPainter* poPainter, const QRect & oRect, int index) const;
virtual void mouseReleaseEvent(QMouseEvent *e);
private:
bool isOn = false, pasTousLesMeme = false;
signals:
void dataModifiedSig();
};
#endif
- QProduitCartoHeaderView.cpp(只有有用的代码来避免长帖子)
#ifndef QPRODUITCARTOHEADERVIEW_H
#include "QProduitCartoHeaderView.h"
#endif
#ifndef QPRODUITCARTODATAMODEL_H
#include "QProduitCartoDataModel.h"
#endif
QProduitCartoHeaderView::QProduitCartoHeaderView(QWidget* parent) : QHeaderView(Qt::Horizontal, parent)
{
}
QProduitCartoHeaderView::~QProduitCartoHeaderView()
{
}
void QProduitCartoHeaderView::setIsOn(bool val)
{
isOn = val;
}
void QProduitCartoHeaderView::setPasTousLesMeme(bool val)
{
//set if all checkboxes have different value or not
pasTousLesMeme = val;
}
void QProduitCartoHeaderView::paintSection(QPainter* poPainter, const QRect & oRect, int index) const
{
poPainter->save();
QHeaderView::paintSection(poPainter, oRect, index);
poPainter->restore();
QStyleOptionButton option;
QRect checkbox_rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator, &option);
checkbox_rect.moveCenter(oRect.center());
// pour la colonne 1
if (index == 0)
{
qDebug() << checkbox_rect << " -- " << oRect;
// position
option.state = QStyle::State_Enabled | QStyle::State_Active;
option.rect = checkbox_rect;
QHeaderView::paintSection(poPainter, checkbox_rect, index);
if (isOn)
{
// on a tout coché
option.state |= QStyle::State_On;
}
else
{ // traite pas tout coché
// on rajoute le troisième état (third state)
// quand on n'a pas tout coché mais pas tout décoché non plus
if ( pasTousLesMeme )
{
option.state |= QStyle::State_NoChange;
}
else
{
// et si on a tout décoché, on décoche (isOn = false et pasTouslesMemes=false)
option.state |= QStyle::State_Off;
}
}
// on redessine alors la checkbox
this->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, poPainter);
}
}
void QProduitCartoHeaderView::mouseReleaseEvent(QMouseEvent *e)
{
QHeaderView::mouseReleaseEvent(e);
}
bool QProduitCartoHeaderView::all_first_columns_checked(int logicalIndex)
{
//code to check if all first colum is checked
}
bool QProduitCartoHeaderView::all_first_columns_unchecked(int logicalIndex)
{
//code to check if all first colum is unchecked
}
void QProduitCartoHeaderView::on_sectionClicked(int logicalIndex)
{
// code pour le click du header contenant les checkboxes
QProduitCartoDataModel* the_Model = (QProduitCartoDataModel*) this->model();
if (logicalIndex == 0)
{
// on update l'état du checkbox principale (si isOn = true, la checkbox est cochée)
if (isOn)
{
// si elle est cochée, on la met à false (pour flip/flop)
isOn = false;
// mais si tout est décoché, alors, on met la checkbox à false
if (all_first_columns_unchecked(logicalIndex))
{
isOn = true;
}
}
else
{
isOn = true;
if (all_first_columns_checked(logicalIndex))
{
isOn = false;
}
}
this->update();
// fin update
int nbRow = this->model()->rowCount();
// on met tout à false si la majorité est à true
int nbTrue = 0;
if (all_first_columns_checked(logicalIndex))
{
for (int r = 0; r < nbRow; r++)
{
QModelIndex index = this->model()->index(r, logicalIndex);
the_Model->setData(index, false, Qt::CheckStateRole);
}
}
else
{
// on efface d'abord tout
for (int r = 0; r < nbRow; r++)
{
QModelIndex index = this->model()->index(r, logicalIndex);
bool checked = this->model()->data(index, Qt::DisplayRole).toBool();
if (checked)
the_Model->setData(index, false, Qt::CheckStateRole);
}
// Ensuite, on fait le flip/flop
for (int r = 0; r < nbRow; r++)
{
QModelIndex index = this->model()->index(r, logicalIndex);
// update each row of real data
the_Model->setData(index, true, Qt::CheckStateRole);
}
}
}
emit dataModifiedSig();
}