<分区>
我开始了解 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());
}
SectionScene
中的 mousePressEvent
行为如下:使用 ctrl-modifier,它正确地创建了 BezierNode
并将其绘制在 View 上(只有一个使用的 View ,场景绑定(bind)到它)。如果在没有修饰符的情况下左键单击,如果我在 BezierNode
形状之外单击,则一切正常。但是如果我点击它,就会在 items(e->scenePos())
出现段错误。 itemAt(..)
也是如此,当我尝试只使用 QGraphicsScene::mousePressEvent(e)
时。现在好几个小时都无法克服它,所以我想听听你的想法。此外,BezierNode
中的 sceneEvent(QGraphicsSceneEvent* event)
会在每个场景事件上触发,即使它与此项无关。它应该如何?
可在 git 找到完整的可编译项目.