我们如何在内存缓冲区中创建具有SVG图标内容的QIcon
对象?
P.S。最初想要创建QSvgIconEngine,但它隐藏在插件层上,我无法显式创建它。如何从插件加载(考虑到该插件已加载)?
答案 0 :(得分:4)
在这里和那里挖掘了一段时间后,挖掘QIcon本身如何使用svg文件加载图标,这是我学到的:
QIcon
,当使用svg文件(或任何其他图像类型)调用时,它随后会调用addFile()
,它只使用文件的扩展名(QFileInfo::suffix
1)}在Qt中确定将图像文件转换为图标的方法。
该方法(从语义上讲)由QIconEngine
实例确定
QIconEngine
个类;显然有一个插件系统可供使用,它在编译时不可用(至少不是这样)
另一方面; QIcon如何运作?当从QIcon请求图标时,它使用传递给它的信息来确定要使用的引擎,并创建引擎的实例。然后,每次图标需要绘制某些内容时,它会要求引擎绘制一个给定大小的图标。大小用于函数QIconEngine::pixmap()
,它创建一个具有所需大小的像素图,然后方法QIconEngine::paint()
用于绘制该像素图。
因此,根据这些信息,解决方案就是编写一个QIcon将使用的图标引擎,以便根据传递给它的大小生成图标。以下是如何做到这一点:
所以这里是头文件SvgIconEngine.h
#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
#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。
要使用此功能,只需执行以下操作:
std::string iconSvgData = GetTheSvgPlainData();
QIcon theIcon(new SVGIconEngine(iconSvgData));
//Use the icon!
请注意,QIcon取得了引擎对象的所有权。当它被摧毁时它会毁掉它。
玩得开心!
答案 1 :(得分:0)
我们如何创建具有
QIcon
图标内容的SVG
对象 内存缓冲区?
为此,所有必需的功能都通过QSvgRenderer类的外部接口提供。要构造这种类型的渲染器,我们需要使用以下任何一种:
QSvgRenderer(const QByteArray &contents, QObject *parent = Q_NULLPTR);
QSvgRenderer(QXmlStreamReader *contents, QObject *parent = Q_NULLPTR);
或者我们只需加载内容:
bool QSvgRenderer::load(const QByteArray &contents)
bool QSvgRenderer::load(QXmlStreamReader *contents)
并创建实际图标:
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
反转图标颜色。
答案 2 :(得分:0)
我手头没有C ++,但转换起来应该很容易:
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像素图标。