如何在 QGraphicsScene 中添加项目?

发布于 2024-11-27 12:36:45 字数 3359 浏览 1 评论 0原文

我正在尝试在鼠标单击和鼠标光标坐标处的 QGraphicsScene 中添加一些自定义 QGraphicsItems。但这些项目不会添加到与鼠标光标相同的坐标处。

    renderArea::renderArea(QWidget *parent):
            QGraphicsView(parent)
    {
        scene = new QGraphicsScene(this);
        scene->setItemIndexMethod(QGraphicsScene::NoIndex);
        scene->setSceneRect(0, 0, 850, 480);
        setScene(scene);
        setCacheMode(CacheBackground);
        setViewportUpdateMode(BoundingRectViewportUpdate);
        setRenderHint(QPainter::Antialiasing);
        setTransformationAnchor(AnchorUnderMouse);
        scale(qreal(1.0), qreal(1.0));
        setMinimumSize(400, 400);
    }

    void renderArea::mousePressEvent(QMouseEvent *event)
    {
        QPoint p = event->pos();

    updateList(p);
    }

    void renderArea::updateList(const QPoint &p)
    {
        Point point;
        point.point = p;
        point.isSelected = false;
        list.append(point);
        if (list.size() > 1)
            updateClothoid(list[list.size()-2].point, list[list.size()-1].point);
    }

    void renderArea::updateClothoid(const QPoint &p1, const QPoint &p2)
    {
        Clothoid *temp = new Clothoid(p1, p2);

        clothoids.append(temp);

        scene->addItem(temp);
    }

renderArea 是 QGraphicsView,Clothoids 是自定义 QGraphicsItem

    Clothoid::Clothoid(QPoint startPoint, QPoint endPoint)
    {
        sPoint = startPoint;
        ePoint = endPoint;
        startCurvature = 0.0;
        endCurvature = 0.0;
        clothoidLength = sqrt(pow(endPoint.x() - startPoint.x(),2) +
                              pow(endPoint.y() - startPoint.y(),2));
    }    

    QRectF Clothoid::boundingRect() const
        {
            qreal penWidth = 1;

            if ((sPoint.x() < ePoint.x()) && (sPoint.y() < ePoint.y()))
                return QRectF(sPoint.x(), sPoint.y(), ePoint.x() - sPoint.x(), ePoint.y()-sPoint.y())
                .normalized()
                .adjusted(-penWidth, -penWidth, penWidth, penWidth);

            if ((sPoint.x() < ePoint.x()) && (sPoint.y() > ePoint.y()))
                return QRectF(sPoint.x(), ePoint.y(), ePoint.x() - sPoint.x(), sPoint.y() - ePoint.y())
                .normalized()
                .adjusted(-penWidth, -penWidth, penWidth, penWidth);

            if ((sPoint.x() > ePoint.x()) && (sPoint.y() < ePoint.y()))
                return QRectF(ePoint.x(), sPoint.y(), sPoint.x() - ePoint.x(), ePoint.y()-sPoint.y())
                .normalized()
                .adjusted(-penWidth, -penWidth, penWidth, penWidth);

            if ((sPoint.x() > ePoint.x()) && (sPoint.y() > ePoint.y()))
                return QRectF(ePoint.x(), ePoint.y(), sPoint.x() - ePoint.x(), sPoint.y() - ePoint.y())
                .normalized()
                .adjusted(-penWidth, -penWidth, penWidth, penWidth);

            return QRectF();

        }

        void Clothoid::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
        {
            QLineF line(sPoint, ePoint);

            // Draw the line itself
            painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
            painter->drawLine(line);
        }

我猜测我插入项目的坐标属于 GraphicsView,而不是场景,因为在我的应用程序中,场景不覆盖整个视图。但我怎样才能获得我的场景的坐标呢?

I am trying to add some custom QGraphicsItems in a QGraphicsScene on mouse click and at mouse cursor coordinates. But the items are not added at the same coordinates as the mouse cursor's.


    renderArea::renderArea(QWidget *parent):
            QGraphicsView(parent)
    {
        scene = new QGraphicsScene(this);
        scene->setItemIndexMethod(QGraphicsScene::NoIndex);
        scene->setSceneRect(0, 0, 850, 480);
        setScene(scene);
        setCacheMode(CacheBackground);
        setViewportUpdateMode(BoundingRectViewportUpdate);
        setRenderHint(QPainter::Antialiasing);
        setTransformationAnchor(AnchorUnderMouse);
        scale(qreal(1.0), qreal(1.0));
        setMinimumSize(400, 400);
    }

    void renderArea::mousePressEvent(QMouseEvent *event)
    {
        QPoint p = event->pos();

    updateList(p);
    }

    void renderArea::updateList(const QPoint &p)
    {
        Point point;
        point.point = p;
        point.isSelected = false;
        list.append(point);
        if (list.size() > 1)
            updateClothoid(list[list.size()-2].point, list[list.size()-1].point);
    }

    void renderArea::updateClothoid(const QPoint &p1, const QPoint &p2)
    {
        Clothoid *temp = new Clothoid(p1, p2);

        clothoids.append(temp);

        scene->addItem(temp);
    }

renderArea being the QGraphicsView and Clothoids the custom QGraphicsItem


    Clothoid::Clothoid(QPoint startPoint, QPoint endPoint)
    {
        sPoint = startPoint;
        ePoint = endPoint;
        startCurvature = 0.0;
        endCurvature = 0.0;
        clothoidLength = sqrt(pow(endPoint.x() - startPoint.x(),2) +
                              pow(endPoint.y() - startPoint.y(),2));
    }    

    QRectF Clothoid::boundingRect() const
        {
            qreal penWidth = 1;

            if ((sPoint.x() < ePoint.x()) && (sPoint.y() < ePoint.y()))
                return QRectF(sPoint.x(), sPoint.y(), ePoint.x() - sPoint.x(), ePoint.y()-sPoint.y())
                .normalized()
                .adjusted(-penWidth, -penWidth, penWidth, penWidth);

            if ((sPoint.x() < ePoint.x()) && (sPoint.y() > ePoint.y()))
                return QRectF(sPoint.x(), ePoint.y(), ePoint.x() - sPoint.x(), sPoint.y() - ePoint.y())
                .normalized()
                .adjusted(-penWidth, -penWidth, penWidth, penWidth);

            if ((sPoint.x() > ePoint.x()) && (sPoint.y() < ePoint.y()))
                return QRectF(ePoint.x(), sPoint.y(), sPoint.x() - ePoint.x(), ePoint.y()-sPoint.y())
                .normalized()
                .adjusted(-penWidth, -penWidth, penWidth, penWidth);

            if ((sPoint.x() > ePoint.x()) && (sPoint.y() > ePoint.y()))
                return QRectF(ePoint.x(), ePoint.y(), sPoint.x() - ePoint.x(), sPoint.y() - ePoint.y())
                .normalized()
                .adjusted(-penWidth, -penWidth, penWidth, penWidth);

            return QRectF();

        }

        void Clothoid::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
        {
            QLineF line(sPoint, ePoint);

            // Draw the line itself
            painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
            painter->drawLine(line);
        }

I am guessing that the coordinates to which I am inserting the items belong to the GraphicsView and not the scene as in my application the scene doesn't cover the entire view. But how could I get the coordinates of the scene in my case?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我的黑色迷你裙 2024-12-04 12:36:45

你是对的,坐标是相对于 GraphicView 的,而不是

取自 的 场景Qt的文档

返回鼠标光标相对于接收事件的小部件的位置。
如果由于鼠标事件而移动小部件,请使用 globalPos() 返回的全局位置以避免晃动。

希望它们提供方便的功能(摘自 QGraphicsView 文档):

您还可以通过创建 QGraphicsView 的子类并重新实现鼠标和按键事件处理程序来提供自己的自定义场景交互。为了简化您以编程方式与视图中的项目进行交互的方式,QGraphicsView 提供了映射函数mapToScene() 和mapFromScene(),以及项目访问器items() 和itemAt()。这些函数允许您在视图坐标和场景坐标之间映射点、矩形、多边形和路径,并使用视图坐标查找场景上的项目。

因此,您要查找的函数是 mapToScene()可以直接调用,因为 renderArea 继承自 QGraphicsView

void renderArea::mousePressEvent(QMouseEvent *event)
{
    QPoint p = mapToScene(event->pos());
    updateList(p);
}

Edit :注意,mapToScene() 返回一个 QPointF,而不是 QPoint。本身不是问题,但您应该意识到这一点。

You're right, the coordinates are relative to the GraphicView, not the Scene

Taken from the Qt's documentation :

Returns the position of the mouse cursor, relative to the widget that received the event.
If you move the widget as a result of the mouse event, use the global position returned by globalPos() to avoid a shaking motion.

Hopefully, they provide convenience functions (excerpt from the QGraphicsView doc) :

You can also provide your own custom scene interaction, by creating a subclass of QGraphicsView, and reimplementing the mouse and key event handlers. To simplify how you programmatically interact with items in the view, QGraphicsView provides the mapping functions mapToScene() and mapFromScene(), and the item accessors items() and itemAt(). These functions allow you to map points, rectangles, polygons and paths between view coordinates and scene coordinates, and to find items on the scene using view coordinates.

So, the function you're looking for is mapToScene() that you can call directly because renderArea inherits from QGraphicsView

void renderArea::mousePressEvent(QMouseEvent *event)
{
    QPoint p = mapToScene(event->pos());
    updateList(p);
}

Edit : Watch out, mapToScene() returns a QPointF, not a QPoint. Not a problem in itself, but you should be aware of this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文