Qt QGraphicsScene items()分段错误

时间:2014-10-08 12:45:30

标签: c++ qt qgraphicsitem qgraphicsscene

我开始了解QGraphicsScene和Qt的整个QGraphics部分。现在我正在尝试创建一个管理贝塞尔曲线的程序(用于建模机身部分,这就是为什么代码中有“部分”)。

实施QGraphicsScene课程:

class SectionScene : public QGraphicsScene
{
    Q_OBJECT
public:
    explicit SectionScene(Database* database, QObject *parent = 0);
    BezierCurve* currentCurve();
signals:

public slots:
    void focusCurve(BezierCurve* curve);
    void addNode(BezierNode* node);
private:
    void mousePressEvent(QGraphicsSceneMouseEvent* e);
    Database* database;
    BezierCurve* m_currentCurve;
    QPainter* painter;
};

SectionScene::SectionScene(Database* database, QObject *parent) :
    QGraphicsScene(parent)
{
    this->database = database;
    this->setSceneRect(-100,-100,200,200);
    connect(database,SIGNAL(curveFocus(BezierCurve*)),this,SLOT(focusCurve(BezierCurve*)));
    connect(database,SIGNAL(nodeAdd(BezierNode*)),this,SLOT(addNode(BezierNode*)));
    painter = new QPainter();
    addItem(new QGraphicsRectItem(QRectF(0,0,100,100)));
}

void SectionScene::addNode(BezierNode *node)
{
    addItem(node);
    if (node->leftControlPoint()) addItem(node->leftControlPoint());
    if (node->rightControlPoint()) addItem(node->rightControlPoint());
    update();
}

void SectionScene::mousePressEvent(QGraphicsSceneMouseEvent *e)
{
    if (e->button() == Qt::LeftButton && e->modifiers() == Qt::ControlModifier) {
        BezierNode* node = new BezierNode(e->scenePos());
        currentCurve()->appendNode(node);

    } else {
        if (items(e->scenePos()).size()) {
            QGraphicsScene::mousePressEvent(e);
        }
    }
}

BezierNode类,QGraphicsItem

class BezierNode : public QGraphicsItem
{
    Q_INTERFACES(QGraphicsItem)
public:
    enum Type {Symmetric, Smooth, Angular};
    BezierNode(QPointF point = QPointF(0,0), Type type = Symmetric);
    void setPoint(QPointF point);
    QPointF& point();
    void setLeftControlPoint(BezierControlPoint*);
    BezierControlPoint* leftControlPoint();
    void setRightControlPoint(BezierControlPoint*);
    BezierControlPoint* rightControlPoint();
    void setType(Type);
    Type type();

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
    QPainterPath shape() const;



public slots:
//  void mousePressEvent(QGraphicsSceneMouseEvent *event);
    //  void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
    bool sceneEvent(QEvent *event);
private:
    QPointF m_point;
    BezierControlPoint* m_leftControlPoint;
    BezierControlPoint* m_rightControlPoint;
    Type m_type;
    bool m_selected = false;
    bool m_hovered = false;
};

BezierNode::BezierNode(QPointF point, Type type) : QGraphicsItem()
{
    m_point = point;
    m_type = type;
    if (type == Symmetric) {
        BezierControlPoint* leftControlPoint = new BezierControlPoint(point - QPoint(30,0),this);
        BezierControlPoint* rightControlPoint = new BezierControlPoint(point + QPoint(30,0),this);
        setLeftControlPoint(leftControlPoint);
        setRightControlPoint(rightControlPoint);
    }
//  setFlags(ItemIsMovable);
}

QRectF BezierNode::boundingRect() const
{
    qreal size = 7;
    QPointF topLeft = m_point - QPointF(size,-size);
    QPointF bottomRight = m_point + QPointF(size, -size);
    return QRectF(topLeft,bottomRight);
}

void BezierNode::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->drawEllipse(boundingRect());
}

QPainterPath BezierNode::shape() const
{

    QPainterPath path;
    path.addEllipse(boundingRect());
}

mousePressEvent中的SectionScene行为如下:使用ctrl-modifier,它会正确创建BezierNode并在视图上绘制(只使用一个视图,场景绑定到它) 。如果在没有修饰符的情况下左键单击,如果我在BezierNode形状之外单击,则一切正常。但如果我点击它,就会在items(e->scenePos())出现分段错误。同样是itemAt(..),当我尝试QGraphicsScene::mousePressEvent(e)时。现在无法通过它好几个小时,所以我想听听你的想法。此外,sceneEvent(QGraphicsSceneEvent* event)中的BezierNode会触发每个场景事件,即使它与此项目无关。它应该是怎么回事?

完整的可编辑项目可在git找到。

1 个答案:

答案 0 :(得分:1)

QGraphicsItem的boundingRect和shape函数负责在调用QGraphicsScene :: items或itemAt时检查位置是否与项目冲突。

您已将此声明为形状函数: -

QPainterPath BezierNode::shape() const
{

    QPainterPath path;
    path.addEllipse(boundingRect());
}

因此,您错过了返回您已创建的形状。

虽然这可能不是分段错误的原因,但它仍然会导致问题。