我开始了解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找到。
答案 0 :(得分:1)
QGraphicsItem的boundingRect和shape函数负责在调用QGraphicsScene :: items或itemAt时检查位置是否与项目冲突。
您已将此声明为形状函数: -
QPainterPath BezierNode::shape() const
{
QPainterPath path;
path.addEllipse(boundingRect());
}
因此,您错过了返回您已创建的形状。
虽然这可能不是分段错误的原因,但它仍然会导致问题。