如何在内存缓冲区中创建具有SVG图标内容的QIcon对象?
附注:最初想创建QSvgIconEngine,但它隐藏在插件层中,我无法显式地创建它。如何从插件加载(考虑到插件已加载)?
发布于 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
#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取得了engine对象的所有权。当它被摧毁的时候它就会毁掉它。
玩得开心!
发布于 2019-02-21 17:08:44
我手头没有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像素图标。
发布于 2017-04-01 00:00:39
如何在内存缓冲区中创建具有
SVG图标内容的QIcon对象?
为此,所有需要的功能都是通过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来反转图标的颜色。
https://stackoverflow.com/questions/43125339
复制相似问题