首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从内存中的SVG内容创建QIcon

从内存中的SVG内容创建QIcon
EN

Stack Overflow用户
提问于 2017-03-31 02:08:58
回答 3查看 3.6K关注 0票数 3

如何在内存缓冲区中创建具有SVG图标内容的QIcon对象?

附注:最初想创建QSvgIconEngine,但它隐藏在插件层中,我无法显式地创建它。如何从插件加载(考虑到插件已加载)?

EN

回答 3

Stack Overflow用户

发布于 2017-06-26 18:45:29

在深入研究了一段时间之后,并深入了解了QIcon本身是如何使用svg文件加载图标的,下面是我所学到的:

  • QIcon,当使用svg文件(或任何其他图像类型)调用时,它随后调用addFile(),后者只使用文件的扩展名(在Qt中称为QFileInfo::suffix )来确定将图像文件转换为图标的方法。

  • 方法(从语义上讲)是由QIconEngine实例

确定的

显然,我们( Qt开发人员)不能简单地访问每种图像类型的

  • QIconEngine类;显然,有一个要使用的插件系统,而且它在编译时(至少不是简单地)

不可用

另一方面,QIcon是如何工作的?当从QIcon请求图标时,它使用传递给它的信息来确定要使用哪个引擎,并创建该引擎的一个实例。然后,每当图标需要绘制一些东西时,它会要求引擎绘制一个给定大小的图标。大小在函数QIconEngine::pixmap()上使用,该函数创建一个具有所需大小的像素图,然后使用QIconEngine::paint()方法在该像素图上绘制。

因此,给定这些信息,解决方案就是编写一个图标引擎,QIcon将使用该引擎来根据传递给它的大小生成图标。下面是如何做到这一点的:

下面是头文件SvgIconEngine.h

代码语言:javascript
复制
#ifndef SVGICONENGINE_H
#define SVGICONENGINE_H

#include <QIconEngine>
#include <QSvgRenderer>

class SVGIconEngine : public QIconEngine {

  QByteArray data;

public:
  explicit SVGIconEngine(const std::string &iconBuffer);
  void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode,
             QIcon::State state) override;
  QIconEngine *clone() const override;
  QPixmap pixmap(const QSize &size, QIcon::Mode mode,
                 QIcon::State state) override;
signals:

public slots:
};

#endif // SVGICONENGINE_H

下面是实现,SvgIconEngine.cpp

代码语言:javascript
复制
#include "SvgIconEngine.h"
#include <QPainter>

SVGIconEngine::SVGIconEngine(const std::string &iconBuffer) {
  data = QByteArray::fromStdString(iconBuffer);
}

void SVGIconEngine::paint(QPainter *painter, const QRect &rect,
                          QIcon::Mode mode, QIcon::State state) {
  QSvgRenderer renderer(data);
  renderer.render(painter, rect);
}

QIconEngine *SVGIconEngine::clone() const { return new SVGIconEngine(*this); }

QPixmap SVGIconEngine::pixmap(const QSize &size, QIcon::Mode mode,
                              QIcon::State state) {
  // This function is necessary to create an EMPTY pixmap. It's called always
  // before paint()

  QImage img(size, QImage::Format_ARGB32);
  img.fill(qRgba(0, 0, 0, 0));
  QPixmap pix = QPixmap::fromImage(img, Qt::NoFormatConversion);
  {
    QPainter painter(&pix);
    QRect r(QPoint(0.0, 0.0), size);
    this->paint(&painter, r, mode, state);
  }
  return pix;
}

注意:您必须覆盖clone(),因为它是一个抽象方法,而且您必须覆盖pixmap(),因为如果没有它,您就不会有一个用于绘制svg的空像素映射。

要使用此功能,只需执行以下操作:

代码语言:javascript
复制
std::string iconSvgData = GetTheSvgPlainData();
QIcon theIcon(new SVGIconEngine(iconSvgData));
//Use the icon!

请注意,QIcon取得了engine对象的所有权。当它被摧毁的时候它就会毁掉它。

玩得开心!

票数 9
EN

Stack Overflow用户

发布于 2019-02-21 17:08:44

我手头没有c++,但它应该很容易转换:

代码语言:javascript
复制
QtGui.QIcon(
  QtGui.QPixmap.fromImage(
    QtGui.QImage.fromData(
       b'<svg version="1.1" viewBox="0 0 32 32"'
       b' xmlns="http://www.w3.org/2000/svg">'
       b'<circle cx="16" cy="16" r="4.54237"/></svg>')))

此代码将创建带有黑色圆圈的透明32 x 32像素图标。

票数 4
EN

Stack Overflow用户

发布于 2017-04-01 00:00:39

如何在内存缓冲区中创建具有SVG图标内容的QIcon对象?

为此,所有需要的功能都是通过QSvgRenderer类的外部接口提供的。要构造这种类型的渲染器,我们需要使用以下两种方法之一:

代码语言:javascript
复制
QSvgRenderer(const QByteArray &contents, QObject *parent = Q_NULLPTR);
QSvgRenderer(QXmlStreamReader *contents, QObject *parent = Q_NULLPTR);

或者,我们可以使用以下命令加载内容:

代码语言:javascript
复制
bool QSvgRenderer::load(const QByteArray &contents)
bool QSvgRenderer::load(QXmlStreamReader *contents)

并创建实际的图标:

代码语言:javascript
复制
QIcon svg2Icon(const QByteArray& svgContent, QPainter::CompositionMode mode = 
   QPainter::CompositionMode_SourceOver)
{
    return QIcon(util::svg2Pixmap(svgContent, QSize(128, 128), mode));
}

QPixmap svg2Pixmap(const QByteArray& svgContent,
   const QSize& size,
   QPainter::CompositionMode mode)
{
    QSvgRenderer rr(svgContent);
    QImage image(size.width(), size.height(), QImage::Format_ARGB32);
    QPainter painter(&image);
    painter.setCompositionMode(mode);
    image.fill(Qt::transparent);
    rr.render(&painter);
    return QPixmap::fromImage(image);
}

我们也可以使用其他的合成模式,比如QPainter::RasterOp_NotSourceOrDestination来反转图标的颜色。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43125339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档