2014-10-08 3 views
0

Qt의 전체 QGraphics 및 QGraphicsScene을 알게되었습니다. 이제 저는 베니어 곡선을 관리하는 프로그램을 만들려고합니다 (동체 섹션을 모델링하기 위해 코드에 "섹션"이있는 이유입니다).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 행동하는 것은 다음입니다 : 제대로 BezierNode를 만들고 그것을 그립니다 Ctrl 키 수정과 함께 보기 (단 하나의보기 만 사용됨, 장면이 묶여 있음). 수식어가없는 왼쪽 클릭이있는 경우 BezierNode 바깥 쪽을 클릭하면 모든 것이 괜찮습니다. 하지만 클릭하면 items(e->scenePos())에 세분화 오류가 발생합니다. 동일한 것은 itemAt(..)이었고 나는 단지 QGraphicsScene::mousePressEvent(e) 만 시도했을 때였습니다. 몇 시간 동안 지나갈 수 없으므로 나는 당신의 생각을 듣고 싶습니다. 또한 (BezierNode)은이 항목과 관련이 없더라도 모든 장면 이벤트에서 트리거됩니다. 그것이 어떻게되어야 하는가?

전체 컴파일 가능한 프로젝트는 git에서 찾을 수 있습니다.

+1

디버거가'items (..) '의 소유자가'e '인수가 null이라고 말합니까? – cmannett85

+2

@morodeer 컴파일러에서 경고를 켜야합니다. 'QPainterPath BezierNode :: shape()'를 반환하지 않는 리턴 타입을 가진 많은 함수가 있습니다. – PeterT

+0

@PeterT, 감사합니다! 다른 경고들 중에서 그것을 잃어 버렸고, 내 머리를 완전히 벗었습니다. 'shape()'에 반환 값을 더하는 것이 도움이되었습니다. – ProdoElmit

답변

1

QGraphicsItem의 boundingRect 및 shape 함수는 QGraphicsScene :: items 또는 itemAt를 호출 할 때 위치와 항목이 충돌하는지 확인해야합니다.

당신은 형상 함수로 이것을 언급했다 : -

QPainterPath BezierNode::shape() const 
{ 

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

그래서 당신은 당신이 만든 모양을 반환 놓치고있어.

세분화 오류가 원인 일 수는 없지만 여전히 문제가 될 수 있습니다.

+1

고마워요! 주석 값에 나와있는 당신과 @PeterT는 리턴 값을 지정하지 않으면 실제로 문제가 발생했습니다. 컴파일러의 경고를 들여다보아야한다. – ProdoElmit