我正在開始瞭解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());
}
在mousePressEvent
在SectionScene
行爲如下:使用Ctrl-修飾得當創建BezierNode
並繪製它視圖(只有一個視圖被使用,場景被綁定到它)。如果在沒有修飾符的情況下點擊鼠標左鍵,那麼如果我點擊BezierNode
形狀以外的位置,就可以了。但是如果我點擊它,則會出現分段錯誤items(e->scenePos())
。與itemAt(..)
一樣,當我試圖只是QGraphicsScene::mousePressEvent(e)
。現在無法通過它很多小時,所以我想聽聽你的想法。而且,sceneEvent(QGraphicsSceneEvent* event)
在BezierNode
觸發每個場景事件,即使它不涉及此項目。它是如何應該的?
完整的可編譯項目可在git找到。
您的調試器是否說'items(..)'的所有者爲null,它是'e'參數? – cmannett85 2014-10-08 12:51:20
@morodeer你應該在編譯器中打開警告。有一堆返回類型的函數不會返回任何東西'QPainterPath BezierNode :: shape()'。 – PeterT 2014-10-08 12:58:42
@PeterT,謝謝!在其他警告中失去了它,讓我的頭腦徹底關閉了。將返回值添加到'shape()'幫助。 – ProdoElmit 2014-10-08 13:09:17