我试图了解如何在QGraphicsScene
中重新定义项目的选择和转换方式(一旦选定)。例如,更改线条的长度,移动线条,通过移动其中一个点来更改多边形。
我创建了一个QGraphicsView
的孩子,并开始重载其mousePressEvent
,但似乎QGraphicsItem
捕获了选择和移动操作。我如何覆盖它,因为它们受到保护而且QGraphicsView
的孩子无法看到?
我可以想象我需要在QGraphicsItem::mousePressEvent
中重载myGraphicsItem
,但这意味着我还必须重载QGraphicsScene
来处理myGraphicsItem
?如何在场景移动时处理场景中的选定项目位置?
我有什么例子可以看吗?
我(显然)有点迷失。
更新:根据反馈,我创建了一个QGraphicsItems
的孩子,如下所示:
class baseGraphicItem : public QGraphicsItem
{
public:
explicit baseGraphicItem(QVector<QPoint> data, operationType shape, QObject * parent = 0);
signals:
public slots:
public:
virtual QRectF boundingRect() const;
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
QPainterPath shape() const;
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
private:
QPolygon vertex;
operationType shapeType;
};
baseGraphicItem::baseGraphicItem(QVector<QPoint> data, operationType shape, QObject *parent) :
QGraphicsItem(), vertex(data), shapeType(shape)
{
qDebug() << vertex;
this->setAcceptHoverEvents(false);
}
这些用于绘画,boundingRect
和形状。
void baseGraphicItem::paint(QPainter * painter, const QStyleOptionGraphicsItem*, QWidget*)
{
int i=0;
// Following needs better code for polygons
do painter->drawLine(vertex.at(i), vertex.at(i+1));
while (i++<vertex.size()-2);
}
QRectF baseGraphicItem::boundingRect() const
{
return vertex.boundingRect();
}
QPainterPath baseGraphicItem::shape() const
{
QPainterPath path;
path.addPolygon(vertex);
return path;
}
不幸的是,选择适用于一行或多边形。但是当一条线在多边形内时,它几乎总是选择多边形而不是线。这是因为boundingRect
还是形状?另外,如何将新坐标存储在QPolygon
顶点中?
感谢
答案 0 :(得分:7)
这完全取决于您重新定义&#34;选择和转换项目的方式的确切含义&#34;
让我们以QGraphicsLineItem为例。
如果我希望这个项目可以移动,我可以调用它的函数setFlag(QGraphicsItem :: ItemIsMovable)。现在可以在场景中单击并移动项目。当然,这假设该项是可选的,这可以通过设置标志QGraphicsItem :: ItemIsSelectable来实现。
现在,如果我想能够改变一条线的点,我可能会使用它的setLine函数并继续重新定义线。但是,最好直接从QGraphicsItem继承并创建我自己的。
class MyLine : public QGraphicsItem
{
Q_OBJECT
public:
virtual QRectF boundingRect();
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
};
因此,这是我从QGraphicsItem继承的最低要求,因为在QGraphicsItem中boundingRect和paint函数是纯虚拟的。
所以,现在我们可以在课程中添加起点和终点: -
class MyLine : public QGraphicsItem
{
Q_OBJECT
public:
virtual QRectF boundingRect();
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
private:
QPointF m_pointA;
QPointF m_pointB;
};
接下来,类需要在paint函数中绘制自己: -
void MyLine::paint(QPainter * painter, const QStyleOptionGraphicsItem* , QWidget*)
{
// The painter's pen and brush could be set here first
// Draw the line
painter->drawLine(m_pointA, m_pointB);
}
完成此类的最后一件事是boundingRect函数,它表示类的可见区域: -
QRectF MyLine::boundingRect()
{
return QRectF(m_pointA, m_pointB);
}
虽然这个类在功能上是完整的,但是当行是水平时你会发现边界矩形非常大,这在选择对象时是个问题,所以我们可以覆盖形状函数来解决这个问题
QPainterPath MyLine::shape() const
{
QPainterPath path;
path.moveTo(m_pointA);
path.lineTo(m_pointB);
return path;
}
现在我们有了自己的行类,我们可以添加mouseEvent处理程序: -
class MyLine : public QGraphicsItem
{
Q_OBJECT
public:
virtual QRectF boundingRect();
QPainterPath shape() const
virtual void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
virtual void mousePressEvent(QGraphicsSceneMouseEvent * event);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * event);
private:
QPointF m_pointA;
QPointF m_pointB;
};
使用事件处理程序,您需要在mouseMoveEvent中单击鼠标时进行存储。鼠标事件最接近的点(m_pointA或m_PointB)是您可以在mouseMoveEvent中移动和更新的点,直到调用mouseReleaseEvent。
如果mousePressEvent中的原始mouseEvent更接近中心,而不是其中一个点,则只需将事件转发给父类,即可移动整行。
当然,您可以将此作为带有点列表的多边形的模板,然后在绘画中绘制,添加到painterPath的形状并在鼠标事件中进行操作。
答案 1 :(得分:0)
正如this answer所提到的,在QGraphicItem
本身中执行此操作可能更容易,尤其是如果操作特定于某些项目。在这种情况下,以下代码显示了它是如何完成的:
#include <QtWidgets>
class Item : public QGraphicsRectItem
{
public:
Item() {
setRect(0, 0, 100, 100);
setFlag(QGraphicsItem::ItemIsMovable, true);
}
void mousePressEvent(QGraphicsSceneMouseEvent *event) {
qDebug() << "Item";
QGraphicsRectItem::mousePressEvent(event);
}
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsView view;
QGraphicsScene *scene = new QGraphicsScene;
scene->addItem(new Item());
view.setScene(scene);
view.resize(400, 400);
view.show();
return app.exec();
}
#include "main.moc"
有关详细信息,请参阅QGraphicsItem documentation。
如果您只对可以应用于任何QGraphicsItem
子类的项目进行通用操作,那么请查看Elastic Nodes Example。