QGraphicsSvgItem: could not display correct position of elements



  • Hi,

    sorry if this seem old question, but since i tried to do research whole the days but still could not find out exact answer. i'm newbie with great Qt world :).

    I have a SVG map file (map.svg) that include some map Zone elements.

    When i try to show the SVG on GraphicScene , its all working BUT the problem that when i tried to render some Zone with customeQGraphicsSvgItem class with difference color, the Zones always set at Center of the Scene(or top left if i change the View's alignment ).

    What i'm doing wrong please? How could i display** child elements **of a SVG to correct position like how we open its using browser?



  • Hi,

    i solved the problem myself but i still leave the question here in case someon esle needed.

    This is the code i did to display the Svg Map and Zone:

    QGraphicsScene *scene = new QGraphicsScene(ui->graphicsView);
    QSvgRenderer    *svgRender  =    new QSvgRenderer(QString("://files/map.svg"));
    
    scene->setSceneRect(0,0,400,900); //set rect as SVG viewport
    
    //map background
    QGraphicsSvgItem *mapBackground = new QGraphicsSvgItem("://files/map.svg");
    mapBackground->setParent(scene);
    mapBackground->setPos(0,0);
    scene->addItem(mapBackground);
    
    
    MapZone *zone1  =   new MapZone();
    scene->setBackgroundBrush(QBrush(Qt::gray, Qt::SolidPattern));
    zone1->setSharedRenderer(svgRender);
    zone1->setElementId("zone1");
    zone1->setParentItem(mapBackground);
    zone1->setToolTip("this is zone 1");
    
    QRectF bound    =   svgRender->boundsOnElement("zone1");
    
    zone1->setPos(bound.x(), bound.y());  // this code is must to set correct posisiton
    scene->addItem(zone1);
    
    ui->graphicsView->setScene(scene);

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Glad you found out and thanks for sharing !

    Since you have it working now, please mark the thread as solved using the "Topic Tool" button so that other forum users may know a solution has been found :)



  • Please correct me if I'm wrong but I think the issue is not solve, qt least not with Qt4.8.

    This minimal example shows the svg elements at the wrong place:

    #include <QApplication>
    #include <QByteArray>
    #include <QtSvg>
    
    QByteArray g_svg_content(
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
        ""
        "<svg height=\"200\" width=\"200\">"
        "  <circle id=\"blue\""
        "    cx=\"50\""
        "    cy=\"50\""
        "    r=\"40\""
        "    fill=\"blue\" />"
        "  <circle id=\"red\""
        "    cx=\"99\""
        "    cy=\"99\""
        "    r=\"30\""
        "    fill=\"red\" />"
        "</svg>");
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        QGraphicsScene scene;
        QGraphicsView view(&scene);
    
        QSvgRenderer* renderer = new QSvgRenderer(g_svg_content);
    
        QString element_id;
        element_id = QString("blue");
        if(renderer->elementExists(element_id))
        {
            QGraphicsSvgItem* svg = new QGraphicsSvgItem();
            svg->setSharedRenderer(renderer);
            svg->setElementId(element_id);
            QRectF rect = renderer->boundsOnElement(element_id);
            svg->setPos(rect.bottomLeft());
            scene.addItem(svg);
        }
    
        element_id = QString("red");
        if(renderer->elementExists(element_id))
        {
            QGraphicsSvgItem* svg = new QGraphicsSvgItem();
            svg->setSharedRenderer(renderer);
            svg->setElementId(element_id);
            QRectF rect = renderer->boundsOnElement(element_id);
            svg->setPos(rect.bottomLeft());
            scene.addItem(svg);
        }
    
        view.show();
    
        return app.exec();
    }
    

    The circles are overlapping instead of just touching each other. What is correct way to achieve showing only parts of an svg file at the correct location? Thanks for help!



  • I also probably found the answer myself, the problem was the use of rect.bottomLeft() instead of rect.topLeft().

    The fully working example is then:

    #include <QApplication>
    #include <QByteArray>
    #include <QtSvg>
    
    QByteArray g_svg_content(
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>"
        ""
        "<svg height=\"200\" width=\"200\">"
        "  <circle id=\"blue\""
        "    cx=\"50\""
        "    cy=\"50\""
        "    r=\"40\""
        "    fill=\"blue\" />"
        "  <circle id=\"red\""
        "    cx=\"99\""
        "    cy=\"99\""
        "    r=\"30\""
        "    fill=\"red\" />"
        "</svg>");
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        QGraphicsScene scene;
        QGraphicsView view(&scene);
    
        QSvgRenderer* renderer = new QSvgRenderer(g_svg_content);
    
        QString element_id;
        element_id = QString("blue");
        if(renderer->elementExists(element_id))
        {
            QGraphicsSvgItem* svg = new QGraphicsSvgItem();
            svg->setSharedRenderer(renderer);
            svg->setElementId(element_id);
            QRectF rect = renderer->boundsOnElement(element_id);
            svg->setPos(rect.topLeft());
            scene.addItem(svg);
        }
    
        element_id = QString("red");
        if(renderer->elementExists(element_id))
        {
            QGraphicsSvgItem* svg = new QGraphicsSvgItem();
            svg->setSharedRenderer(renderer);
            svg->setElementId(element_id);
            QRectF rect = renderer->boundsOnElement(element_id);
            svg->setPos(rect.topLeft());
            scene.addItem(svg);
        }
    
        view.show();
    
        return app.exec();
    }
    
    

    Hope this helps!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.