组成的QGraphicsItem无法检测对子项目的点击

时间:2018-07-27 08:16:45

标签: c++ qt qt5 qgraphicsscene qgraphicsitem

我正在尝试对b'Fortran compilers found:\n --fcompiler=gnu95 GNU Fortran 95 compiler (7)\n' 做一个简单的扩展,使我能够调整矩形的大小并使用鼠标将其移动。我在要启用拖动的拐角处使用椭圆形拱形对手柄进行建模,并将其实现为QGraphicsRectItem s:

QGraphicsEllipseItem

我希望能够检测矩形和手柄项上的点击(这是必要的,因为如果矩形变得太小,则手柄是唯一易于单击的区域),所以我想扩展{{ 1}}将子项的路径添加到返回的class QGraphicsBoxWithHandlesItem : public QObject, public QGraphicsRectItem { Q_OBJECT typedef enum { None, BottomLeft, TopRight } ActiveAnchor; private: QGraphicsEllipseItem m_anchorBottomLeft; QGraphicsEllipseItem m_anchorTopRight; float m_anchorRadius; ActiveAnchor m_activeAnchor; public: QGraphicsBoxWithHandlesItem(QRectF r, float handlesRadius = 20.0, QGraphicsItem *parent = nullptr); void setAnchorRadius(float radius); float getAnchorRadius(); QPainterPath shape() const; protected: void mousePressEvent(QGraphicsSceneMouseEvent * event); void mouseMoveEvent(QGraphicsSceneMouseEvent * event); void mouseReleaseEvent(QGraphicsSceneMouseEvent * event); }; 中(调整坐标以使其相对于父项):

QGraphicsRectItem::shape()

但是,我得到的是,现在完全忽略了手柄区域内的单击,只处理了矩形中央区域的单击。

在具有非平凡形状的情况下,扩展其可点击区域的正确方法是什么?

更新:我尝试在手柄上设置QPainterPath标志,现在,如果单击它,就会看到它被选中。但是,我的父母中仍然没有任何QPainterPath QGraphicsBoxWithHandlesItem::shape() const { auto curShape = QGraphicsRectItem::shape(); curShape.addPath( mapFromItem(&m_anchorBottomLeft, m_anchorBottomLeft.shape()) ); curShape.addPath( mapFromItem(&m_anchorTopRight, m_anchorTopRight.shape()) ); return curShape; } 。我在做什么错了?

编辑:

这是构造函数的实现:

ItemIsSelectable

1 个答案:

答案 0 :(得分:2)

您的QGraphicsEllipseItem位于基础项目的顶部,因此不会发生鼠标事件。

您要做的是使用sceneEventFilter,但是由于QGraphicsEllipseItem是主要项的子项,因此它们永远不会移动,因此它们不应该具有父项,而应该将其直接添加到场景中。

完整功能通过以下代码实现:

*。h

#ifndef QGRAPHICSBOXWITHHANDLESITEM_H
#define QGRAPHICSBOXWITHHANDLESITEM_H

#include <QGraphicsRectItem>
#include <QObject>

class QGraphicsBoxWithHandlesItem : public QObject, public QGraphicsRectItem
{
    Q_OBJECT
    enum ActiveAnchor{
        None,
        BottomLeft,
        TopRight
    };

public:
    QGraphicsBoxWithHandlesItem(QRectF r, float handlesRadius = 20.0, QGraphicsItem *parent = nullptr);
protected:
    QVariant itemChange(GraphicsItemChange change, const QVariant &value);
    bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
private:
    QGraphicsEllipseItem m_anchorBottomLeft;
    QGraphicsEllipseItem m_anchorTopRight;
    float m_anchorRadius;
    ActiveAnchor m_activeAnchor;
};

#endif // QGRAPHICSBOXWITHHANDLESITEM_H

*。cpp

#include "qgraphicsboxwithhandlesitem.h"

#include <QEvent>
#include <QGraphicsScene>
#include <QDebug>

QGraphicsBoxWithHandlesItem::QGraphicsBoxWithHandlesItem( QRectF r, float handlesRadius, QGraphicsItem * parent) :
    QGraphicsRectItem(parent),
    m_anchorRadius(handlesRadius),
    m_activeAnchor(None)
{
    setFlag(QGraphicsItem::ItemIsMovable);
    setFlag(QGraphicsItem::ItemIsSelectable);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges);

    setRect(r);

    m_anchorBottomLeft.setRect(-m_anchorRadius, -m_anchorRadius, m_anchorRadius*2, m_anchorRadius*2);
    m_anchorBottomLeft.setPos(rect().bottomLeft());
    m_anchorBottomLeft.setSpanAngle(90 * 16); // angle is in 16ths of degree
    //m_anchorBottomLeft.setParentItem(this);
    m_anchorBottomLeft.setFlag(QGraphicsItem::ItemIsMovable);
    m_anchorBottomLeft.setFlag(QGraphicsItem::ItemIsSelectable);

    m_anchorTopRight.setRect(-m_anchorRadius, -m_anchorRadius, m_anchorRadius*2, m_anchorRadius*2);
    m_anchorTopRight.setPos(rect().topRight());
    m_anchorTopRight.setStartAngle(180 * 16); // angle is in 16ths of degree
    m_anchorTopRight.setSpanAngle(90 * 16); // angle is in 16ths of degree
    //m_anchorTopRight.setParentItem(this);
    m_anchorTopRight.setFlag(QGraphicsItem::ItemIsMovable);
    m_anchorTopRight.setFlag(QGraphicsItem::ItemIsSelectable);
}

QVariant QGraphicsBoxWithHandlesItem::itemChange(GraphicsItemChange change, const QVariant & value){
    if(change == QGraphicsItem::ItemSceneHasChanged){
        if(scene()){
            scene()->addItem(&m_anchorBottomLeft);
            scene()->addItem(&m_anchorTopRight);
            m_anchorBottomLeft.installSceneEventFilter(this);
            m_anchorTopRight.installSceneEventFilter(this);
        }
    }
    else if (change == QGraphicsItem::ItemPositionHasChanged) {
        m_anchorBottomLeft.setPos(mapToScene(rect().bottomLeft()));
        m_anchorTopRight.setPos(mapToScene(rect().topRight()));
    }
    return QGraphicsRectItem::itemChange(change, value);
}

bool QGraphicsBoxWithHandlesItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
{
    if(watched == &m_anchorTopRight){
        switch (event->type()) {
        case QEvent::GraphicsSceneMousePress:{
            //mousePressEvent
            qDebug()<<"mousePressEvent m_anchorTopRight";
            break;
        }
        case QEvent::GraphicsSceneMouseMove:{
            // mouseMoveEvent
            QRectF r = rect();
            auto p = m_anchorTopRight.mapToScene(m_anchorTopRight.rect().center());
            r.setTopRight(mapFromScene(p));
            setRect(r);
            qDebug()<<"mouseMoveEvent m_anchorTopRight";
            break;
        }
        case QEvent::GraphicsSceneMouseRelease :{
            //mouseReleaseEvent
            qDebug()<<"mouseReleaseEvent m_anchorTopRight";
            break;
        }
        }
    }

    if(watched == &m_anchorBottomLeft){
        switch (event->type()) {
        case QEvent::GraphicsSceneMousePress:{
            //mousePressEvent
            qDebug()<<"mousePressEvent m_anchorBottomLeft";
            break;
        }
        case QEvent::GraphicsSceneMouseMove:{
            // mouseMoveEvent
            QRectF r = rect();
            auto p = m_anchorBottomLeft.mapToScene(m_anchorBottomLeft.rect().center());
            r.setBottomLeft(mapFromScene(p));
            setRect(r);
            qDebug()<<"mouseMoveEvent m_anchorBottomLeft";
            break;
        }
        case QEvent::GraphicsSceneMouseRelease :{
            //mouseReleaseEvent
            qDebug()<<"mouseReleaseEvent m_anchorBottomLeft";
            break;
        }
        }
    }
    return  QGraphicsRectItem::sceneEventFilter(watched, event);
}