gpt4 book ai didi

c++ - 带复选框的 QHeaderView - 如何区分单击标题复选框与单击单元格中的任意位置

转载 作者:行者123 更新时间:2023-12-03 07:23:13 35 4
gpt4 key购买 nike

我有一个自定义标题 QProduitCartoHeaderView在继承自 QHeaderView 的类中定义.
在我的标题中,我有一个复选框用于选中/取消选中同一列中的所有复选框
对于所有数据行。
enter image description here
目前,当我单击第一列(带复选框的)的标题单元格中的任意位置时,
它检查标题复选框。
我想做的是仅在单击 时选中复选框。正好在它上面,如果我单击外部( 但仍在单元格内 )对第一列进行排序。
我试图调整复选框矩形的大小(如下面的片段中的 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();
    }

    最佳答案

    您可以跟踪鼠标并重新实现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, const QRect &rect, 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);
    }

    关于c++ - 带复选框的 QHeaderView - 如何区分单击标题复选框与单击单元格中的任意位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64440913/

    35 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com