2014-10-08 67 views
0

我正在開始瞭解Qt的QGraphicsScene和整個QGraphics的一部分。現在我試圖創建一個管理貝塞爾曲線的程序(用於模擬機身部分,這就是爲什麼代碼中有「部分」)。Qt QGraphicsScene項目()分段錯誤

實現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()); 
} 

mousePressEventSectionScene行爲如下:使用Ctrl-修飾得當創建BezierNode並繪製它視圖(只有一個視圖被使用,場景被綁定到它)。如果在沒有修飾符的情況下點擊鼠標左鍵,那麼如果我點擊BezierNode形狀以外的位置,就可以了。但是如果我點擊它,則會出現分段錯誤items(e->scenePos())。與itemAt(..)一樣,當我試圖只是QGraphicsScene::mousePressEvent(e)。現在無法通過它很多小時,所以我想聽聽你的想法。而且,sceneEvent(QGraphicsSceneEvent* event)BezierNode觸發每個場景事件,即使它不涉及此項目。它是如何應該的?

完整的可編譯項目可在git找到。

+1

您的調試器是否說'items(..)'的所有者爲null,它是'e'參數? – cmannett85 2014-10-08 12:51:20

+2

@morodeer你應該在編譯器中打開警告。有一堆返回類型的函數不會返回任何東西'QPainterPath BezierNode :: shape()'。 – PeterT 2014-10-08 12:58:42

+0

@PeterT,謝謝!在其他警告中失去了它,讓我的頭腦徹底關閉了。將返回值添加到'shape()'幫助。 – ProdoElmit 2014-10-08 13:09:17

回答

1

當調用QGraphicsScene :: items或itemAt時,QGraphicsItem的boundingRect和Shape函數負責檢查位置是否與該物品發生碰撞。

你說這是形狀功能: -

QPainterPath BezierNode::shape() const 
{ 

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

所以你缺少返回你所創建的形狀。

儘管這可能不是導致分段錯誤的原因,但它仍然會導致您的問題。

+1

謝謝!這是真的沒有指定返回值的問題,因爲您和@PeterT在評論中註明。應該看看編譯器的警告。 – ProdoElmit 2014-10-08 13:10:48