Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 组合QGraphicsItem未检测到子项上的单击_C++_Qt_Qt5_Qgraphicsscene_Qgraphicsitem - Fatal编程技术网

C++ 组合QGraphicsItem未检测到子项上的单击

C++ 组合QGraphicsItem未检测到子项上的单击,c++,qt,qt5,qgraphicsscene,qgraphicsitem,C++,Qt,Qt5,Qgraphicsscene,Qgraphicsitem,我正在尝试对qgraphicsrecitem进行一个简单的扩展,它允许我调整矩形的大小并用鼠标移动它。我在要启用拖动功能的拐角处用椭圆拱对控制柄进行建模,实现为QGraphicsEllipseItems: class QGraphicsBoxWithHandlesItem : public QObject, public QGraphicsRectItem { Q_OBJECT typedef enum { None, BottomLeft,

我正在尝试对
qgraphicsrecitem
进行一个简单的扩展,它允许我调整矩形的大小并用鼠标移动它。我在要启用拖动功能的拐角处用椭圆拱对控制柄进行建模,实现为
QGraphicsEllipseItem
s:

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
中(调整坐标以使其相对于父项):

然而,我得到的是,现在手柄区域内的点击被完全忽略,只处理矩形中心区域的点击

当项目具有非平凡形状时,扩展其可点击区域的正确方法是什么

更新:我试图在句柄上设置
ItemIsSelectable
标志,现在,如果我单击它,我看到它被选中。但是,我仍然没有在父级中获得任何
mousePressEvent
。我做错了什么

编辑: 这是构造函数实现:

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

    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_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);
}

您的QGraphicsSellipseitem位于基本项之上,因此鼠标事件永远不会出现在您的面前

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

完整功能在以下代码中实现:

*.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
#如果使用无手柄的QGraphicsBox项目
#定义QGRAPHICSBOXWITHHANDLESITEM_H
#包括
#包括
类QGraphicsBoxWithHandlesItem:公共QObject,公共QGraphicsRecItem
{
Q_对象
枚举活动锚{
没有一个
左下角,
右上角
};
公众:
QGraphicsBoxWithHandlesItem(QRectF r,float handlesRadius=20.0,QGraphicsSitem*父项=nullptr);
受保护的:
QVariant项目变更(图形站点变更、常量QVariant和值);
bool sceneEventFilter(QGraphicsItem*监视,QEvent*事件);
私人:
QGraphicsSellipseitem m_anchorBottomLeft;
QGraphics Sellipseitem m_anchorTopRight;
浮动m_anchorRadius;
主动锚m_主动锚;
};
#endif//qgraphicsboxwithhandles项目
*.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);
}
#包括“qgraphicsboxwithhandlesitem.h”
#包括
#包括
#包括
QGraphicsBoxWithHandlesItem::QGraphicsBoxWithHandlesItem(QRectF r、浮点handlesRadius、QGraphicsSiteM*父项):
QGraphicsRectItem(父级),
m_anchorRadius(handlesRadius),
m_activeAnchor(无)
{
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.设置角度(90*16);//角度为16度
//m_anchorBottomLeft.setParentItem(此项);
setFlag(QGraphicsItem::ItemIsMovable);
m_anchorBottomLeft.setFlag(QGraphicsItem::itemisselect);
m_anchorTopRight.setRect(-m_anchorRadius,-m_anchorRadius,m_anchorRadius*2,m_anchorRadius*2);
m_anchotopright.setPos(rect().topRight());
m_anchorTopRight.设置起始角度(180*16);//角度为16度
m_anchorTopRight.设置角度(90*16);//角度为16度
//m_AnchortoRight.setParentItem(此项);
m_anchorTopRight.setFlag(QGraphicsItem::ItemIsMovable);
m_anchorTopRight.setFlag(QGraphicsItem::itemisselect);
}
QVariant QGraphicsBoxWithHandlesItem::itemChange(GraphicsSitemChange更改,常量QVariant和值){
if(change==QGraphicsItem::ItemSceneHasChanged){
如果(场景()){
场景()->附加项(&m_anchorBottomLeft);
场景()->附加项(&m_AnchortoRight);
m_anchorBottomLeft.installSceneEventFilter(此);
m_anchorTopRight.installSceneEventFilter(此);
}
}
else if(change==QGraphicsItem::ItemPositionHasChanged){
m_anchorBottomLeft.setPos(映射到场景(rect().bottomLeft());
m_anchotopright.setPos(映射到场景(rect().topRight());
}
返回qgraphicsrecitem::itemChange(change,value);
}
bool QGraphicsBoxWithHandlesItem::sceneEventFilter(QGraphicsSitem*监视,QEvent*事件)
{
如果(观看==&m_AnchortoRight){
开关(事件->类型(){
案例QEvent::GraphicsCenemousePress:{
//鼠标垫

qDebug()你是如何将m_anchorBottomLeft和m_AnchorToRight添加到场景中的?好问题。我不确定。它们是root
Rect
项的子项,我将其添加到场景中。我假设这些子项是与父项一起添加的,但我不确定情况是否如此。当我们需要解决此问题时,我们使用@ypnos谢谢,我会定义我真的想看看它!(我希望我昨天找到了它。)我仍然想知道我的代码中发生了什么,但是,如果只是想知道在我再次需要它时如何做:)谢谢,我试过了代码,它似乎起了作用(我仍然需要用我在原始代码中的一些东西来修改它,但这确实满足了我的需要)。
#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);
}