Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to add SVG widget to MainWindow?



  • I have a class derived from QMainWindow, so far I'm adding widgets to the window by simply adding the window as the parent of the widget. I haven't had to implement a paintEvent yet.

    How can I use the same technique to render the SVG in the window? This is what I have so far:

    1. I read the SVG in as part of the XML, the SVG is:
    <svg id="svgLED" width="640" height="480" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <linearGradient id="svg_6" x1="0" y1="0" x2="1" y2="0">
          <stop stop-color="#bfbfbf" offset="0"/>
          <stop stop-color="#404040" offset="1"/>
        </linearGradient>
        <linearGradient id="svg_11" x1="0" y1="0" x2="1" y2="1" spreadMethod="pad">
          <stop stop-color="#dd0000" stop-opacity="0.992188" offset="0"/>
         <stop stop-color="#820101" stop-opacity="0.988281" offset="1"/>
        </linearGradient>
        <linearGradient id="svg_14" x1="0" y1="0" x2="1" y2="1" spreadMethod="pad">
          <stop stop-color="#ffffff" stop-opacity="0.996094" offset="0"/>
          <stop stop-color="#d30606" stop-opacity="0.984375" offset="0.703125"/>
        </linearGradient>
      </defs>
      <g>
        <circle id="svgLED@[id]_c1" fill="url(#svg_6)" 
    		stroke-width="17.5" stroke-linecap="round" 
    		cx="320" cy="240" r="196.125" id="svg_3" 
    		fill-opacity="0.77" transform="rotate(90, 320, 240)"/>
        <circle id="svgLED@[id]_c2" fill="url(#svg_6)" 
    		stroke-width="17.5" stroke-linecap="round" 
    		fill-opacity="0.64" cx="319.252837" cy="239.999045" 
    		r="160" id="svg_7"/>
        <circle id="svgLED@[id]_c3" fill="url(#svg_11)" stroke-width="17.5" 
    		stroke-linecap="round" cx="320.000535" cy="240.001698" r="150"/>
        <ellipse id="svgLED@[id]_e1" fill="url(#svg_14)" stroke-width="17.5" 
    		 stroke-linecap="round" cx="250.179609" cy="170.124194" 
    		 rx="75.675959" ry="44.402987" id="svg_20" 
    		 transform="rotate(-47.7626, 250.18, 170.125)"/>
      </g>
    </svg>	
    

    Once this is in my application along with the rest of the XML which isn't shown above I then use the following function to recreate a QByteArray containing only the SVG:

    /**
     * @brief clsXMLnode::bytArrDocument
     * @param pobjNode : Optional, default is nullptr
     * @return Byte Array containing document
     */
    QByteArray clsXMLnode::bytArrDocument(clsXMLnode* pobjNode) {
        QByteArray bytArrDoc;
    
        if ( pobjNode == nullptr ) {
        //Start off with the document header
            bytArrDoc.append(QString("<?xml version='1.0'?>").toLocal8Bit());
        //No node passed so use 'this'
            pobjNode = this;
        }
        QString strNode(clsXMLnode::msccTokenOpen), strName(pobjNode->strGetNodeName());
        strNode += strName;
    
        foreach( const prAttr &attrPr, pobjNode->mlstAttrPrs ) {
            strNode += clsXMLnode::msccSpace + attrPr.first
                     + clsXMLnode::msccEquals + clsXMLnode::msccQuoteSingle
                     + attrPr.second + clsXMLnode::msccQuoteSingle;
        }
        if ( pobjNode->blnHasChildren() == true ) {
            strNode += clsXMLnode::msccTokenClose;
            bytArrDoc.append(strNode.toLocal8Bit());        
    
            foreach( clsXMLnode* pobjChild, pobjNode->mlstChildren ) {
                bytArrDoc.append(bytArrDocument(pobjChild));
            }
            strNode = clsXMLnode::mscszXMLcloseToken2 + strName + clsXMLnode::msccTokenClose;
            bytArrDoc.append(strNode.toLocal8Bit());
        } else {
            strNode += clsXMLnode::mscszXMLcloseToken;
            bytArrDoc.append(strNode.toLocal8Bit());
        }
        return bytArrDoc;
    }
    

    This is what I do so far with the SVG:

    if ( pobjNode->strGetNodeName().compare(clsXMLnode::mscszNodeSVGroot) == 0 ) {
      QString strID = pobjNode->strGetAttribute(clsXMLnode::mscszAttrID);
    
      if ( strID.isEmpty() != true ) {
        clsXMLnode* pobjWinNode = pobjNode->pobjGetWindow();
    
        if ( pobjWinNode != nullptr ) {
          QWidget* pobjPWidget = pobjWinNode->pobjGetWidget();
    
          if ( pobjPWidget != nullptr ) {
            QByteArray bytArrSVG = pobjNode->bytArrDocument();
            pobjNode->mpobjSVGrender = new QSvgRenderer(bytArrSVG, pobjPWidget);
          }
        }
      }
    }
    

    I see everything else in my window except the SVG, can you see anything missing?


  • Qt Champions 2019

    @SPlatten said in How to add SVG widget to MainWindow?:

    QSvgWidget* pobjSVGwidget = new QSvgWidget(pobjPWidget);
    pobjSVGwidget->load(bytArrSVG);

    You never call show() on the widget, so why should it be visible?



  • You need a QSvgWidget...A "renderer" won't show automatically...



  • @Bonnie , thank you, how to I put that together with what I have as the QSvgWidget doesn't take a QByteArray and I cannot see a method to set the renderer?



  • @SPlatten
    QSvgWidget can take a QByteArray, just create one and use QSvgWidget::load(const QByteArray &contents)



  • I've edited my source:

    if ( pobjNode->strGetNodeName().compare(clsXMLnode::mscszNodeSVGroot) == 0 ) {
      QString strID = pobjNode->strGetAttribute(clsXMLnode::mscszAttrID);
    
      if ( strID.isEmpty() != true ) {
        clsXMLnode* pobjWinNode = pobjNode->pobjGetWindow();
    
        if ( pobjWinNode != nullptr ) {
          QWidget* pobjPWidget = pobjWinNode->pobjGetWidget();
    
          if ( pobjPWidget != nullptr ) {
            QByteArray bytArrSVG = pobjNode->bytArrDocument();
            QSvgWidget* pobjSVGwidget = new QSvgWidget(pobjPWidget);
            pobjSVGwidget->load(bytArrSVG);
          }
        }
      }
    }
    

    I've single stepped all the way to load, but I don't see anything in the window. I thought I may need to apply a position to the SVG, however I've tried both:

    <svg id="svgLED" x="20" y="20" width="640" height="480" xmlns="http://www.w3.org/2000/svg">
    

    No better, then tried:

    <g transform="translate(20,20)">
    

    Again, no better.


  • Qt Champions 2019

    @SPlatten said in How to add SVG widget to MainWindow?:

    QSvgWidget* pobjSVGwidget = new QSvgWidget(pobjPWidget);
    pobjSVGwidget->load(bytArrSVG);

    You never call show() on the widget, so why should it be visible?



  • @jsulm , Excellent, thank you, thats done the trick!


Log in to reply