3

I am using SVG images in my icons for QToolButtons. But I need to be able to change the size of the tool button and I need the icon to scale up or down. My SVG icons have native size of 24 (pixels). The trouble with QIcon is that they do not scale up above the native size. (see attempt0... in my code)

So I tried another approach, I overriden resizeEvent and used QToolButton.setIconSize(event.size()) which worked perfect, it allowed scaling up and down without limits. (see attempt1... in my code)

But here comes my problem. I do need to make some pixel-wise color transform to my rendered icon. Therefore I need to get QImage which I can obtain from QPixmap. But the problem is that I cannot get a SVG image rendered to a pixmap bigger than the SVG native size. The pixmap itself is bigger but the image is still small, aligned to the center of the pixmap. I tried three different approaches, none of them worked. (see attempt2... to attempt4... in my code)

My code is here. For simpicity I left out the color pixel-wise transform which I am doing to the obtained pixmap/image.

toolbar.h

#pragma once

#include <QToolButton>

class ToolButton : public QToolButton
{
    Q_OBJECT
public:
    explicit ToolButton(QWidget *parent = nullptr);
protected:
    void resizeEvent(QResizeEvent *event) override;
private:
    void attempt0_thisDoesNotScaleUp();
    void attempt1_thisScalesWellButIdoNotHavePixmap(int w, int h);
    void attempt2_thisDoesNotScaleUp(int w, int h);
    void attempt3_thisDoesNotScaleUp(int w, int h);
    void attempt4_thisDoesNotScaleUp(int w, int h);
    QString m_iconName;
};

toolbar.cpp

#include "toolbutton.h"

#include <QDebug>
#include <QPainter>
#include <QResizeEvent>
#include <QtSvg/QSvgRenderer>

ToolButton::ToolButton(QWidget *parent) :
    QToolButton(parent)
{
    m_iconName = "icon.svg";
    // attempt0_thisDoesNotScaleUp(); // uncomment to try attempt 0
}

void ToolButton::resizeEvent(QResizeEvent *event)
{

    int w = event->size().width();
    int h = event->size().height();

    //attempt1_thisScalesWellButIdoNotHavePixmap(name, w, h); // uncomment to try attempt 1
    //attempt2_thisDoesNotScaleUp(name, w, h); // uncomment to try attempt 2
    //attempt3_thisDoesNotScaleUp(name, w, h); // uncomment to try attempt 3
    //attempt4_thisDoesNotScaleUp(name, w, h); // uncomment to try attempt 4

    QToolButton::resizeEvent(event);
}

void ToolButton::attempt0_thisDoesNotScaleUp()
{
    setIcon(QIcon(m_iconName));
}

void ToolButton::attempt1_thisScalesWellButIdoNotHavePixmap(int w, int h)
{
    setIcon(QIcon(m_iconName));
    setIconSize(QSize(w, h));
}

void ToolButton::attempt2_thisDoesNotScaleUp(int w, int h)
{
    QIcon source(m_iconName);
    QPixmap pixmap = source.pixmap(w, h);
    QIcon icon;
    icon.addPixmap(pixmap);
    setIcon(icon);
}

void ToolButton::attempt3_thisDoesNotScaleUp(int w, int h)
{
    QSvgRenderer renderer(m_iconName);
    QPixmap pm(w, h);
    QPainter painter(&pm);
    renderer.render(&painter, pm.rect());
    QIcon icon;
    icon.addPixmap(pm);
    setIcon(icon);
}

void ToolButton::attempt4_thisDoesNotScaleUp(int w, int h)
{
    QIcon source(m_iconName);
    QPixmap pm(w, h);
    QPainter painter(&pm);
    source.paint(&painter, pm.rect());
    QIcon icon;
    icon.addPixmap(pm);
    setIcon(icon);
}

main.cpp (to show toolbutton as a main window to be able to test resizing)

#include "toolbutton.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    ToolButton w;
    w.show();
    return a.exec();
}

For testing I am using SVG icons from www.iconmonstr.com which have native size of 24x24 pixels. Of course I need to be able scale them above this size.

I guess I am missing something obvious... because QToolButton::setIconSize(someBiggerSize); is able to scale SVG icon up.

  • Try looking through the Qt code to see what the setIconSize does (it's a `QAbstractButton` function). I had a cursory look, but got lost in the web interface here: https://github.com/qt/qtbase/blob/5.11/src/widgets/widgets/qabstractbutton.cpp#L1278. Perhaps having code navigation tools on a locally downloaded copy will also help. – rubenvb Oct 10 '18 at 12:15

1 Answers1

2

Probably the most stupid mistake I have made public here on SO: if I put setIconSize(QSize(w, h)); at the end of each attempt... etc. methods, they all will work fine.

Despite the fact that the mistake was stupid, I will leave the answer here as a reference about how many ways we can use to render SVG.

UPDATE: there is yet another method for rendering SVG directly to QImage mentioned here How to render a scaled SVG to a QImage? This one actually seems best suited for my purpose. No need for intermediary pixmap.