如何解决带有复选框的QHeaderView-如何区分在标题复选框上单击右键与在单元格中的任何位置单击
我在从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,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,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();
}
解决方法
您可以跟踪鼠标并重新实现mousePressEvent(QMouseEvent *event)
和mouseReleaseEvent(QMouseEvent *event)
以确定单击该部分的位置。我在下面创建了一个示例:
myheaderview.h
#ifndef MYHEADERVIEW_H
#define MYHEADERVIEW_H
#include <QHeaderView>
class MyHeaderView : public QHeaderView
{
public:
MyHeaderView(QWidget *parent = nullptr);
QRect visualRectOfColumn(int column) const;
protected:
virtual void paintSection(QPainter *painter,const QRect &rect,int index) const;
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
private:
int press_column_{-1};
bool checkbox_pressed_{false};
};
#endif // MYHEADERVIEW_H
myheaderview.cpp
#include "myheaderview.h"
#include <QPainter>
#include <QMouseEvent>
#include <QDebug>
MyHeaderView::MyHeaderView(QWidget *parent) : QHeaderView(Qt::Horizontal,parent)
{
this->setMouseTracking(true);
}
QRect MyHeaderView::visualRectOfColumn(int column) const
{
int x = sectionViewportPosition(column);
int y = 0;
int h = this->height();
int w = this->sectionSize(column);
return QRect(x,y,w,h);
}
void MyHeaderView::paintSection(QPainter *painter,int index) const
{
painter->save();
QHeaderView::paintSection(painter,rect,index);
painter->restore();
if (index == 0)
{
QStyleOptionButton option;
QRect checkbox_rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator,&option);
checkbox_rect.moveCenter(rect.center());
option.state = QStyle::State_Enabled | QStyle::State_Active;
option.rect = checkbox_rect;
QHeaderView::paintSection(painter,checkbox_rect,index);
this->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox,&option,painter);
}
}
void MyHeaderView::mousePressEvent(QMouseEvent *event)
{
press_column_ = this->visualIndexAt(event->pos().x());
if (press_column_ == -1)
{
checkbox_pressed_= false;
return QHeaderView::mousePressEvent(event);;
}
QStyleOptionButton option;
QRect checkbox_rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator,&option);
checkbox_rect.moveCenter(this->visualRectOfColumn(press_column_).center());
checkbox_pressed_= checkbox_rect.contains(event->pos());
QHeaderView::mousePressEvent(event);
}
void MyHeaderView::mouseReleaseEvent(QMouseEvent *event)
{
int release_column = this->visualIndexAt(event->pos().x());
if (release_column != -1 && press_column_ == release_column)
{
if (release_column != 0)
qDebug() << "sort";
else
{
QStyleOptionButton option;
QRect checkbox_rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator,&option);
checkbox_rect.moveCenter(this->visualRectOfColumn(release_column).center());
if (checkbox_pressed_&& checkbox_rect.contains(event->pos()))
qDebug() << "checkbox";
else if (!checkbox_pressed_&& !checkbox_rect.contains(event->pos()))
qDebug() << "sort";
}
}
press_column_ = -1;
checkbox_pressed_= false;
QHeaderView::mouseReleaseEvent(event);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。