SVG
一般而言,QSS是无法直接使用svg图像的。
那如何才能显示svg呢?我们知道svg的好处有很多,如矢量图,体积小等等
svg本来就是一个document(可参考12),QT提供了QSvgRenderer
用于访问svg doc
QT绘制SVG流程
QSvgRenderer
读取svg内容- 创建
QPixmap
用于容纳svg图像 - 使用
QPainter
绘制svg
PS: 注意QPixmap
设置宽高时需要考虑到DPI,否则会造成图像错位
对于一些控件QLabel
来说,设置setScaledContents(true)、adjustSize()、setSizePolicy(Preferred)
进行缩放
e.g.
// .h
#ifndef __UISVGICON_H__
#define __UISVGICON_H__
#include "UICommon_Global.h"
class QString;
class QPixmap;
class UP3DUICOMMON_EXPOT UISvgIcon
{
public:
explicit UISvgIcon(const QString& svgPath);
~UISvgIcon();
public:
/// @brief 获取SVG图像
const QPixmap& pixmap();
/// @brief 填充色属性修改
void setFill(const QString &targetName, const QString &color);
private:
class Pimpl;
std::unique_ptr<Pimpl> impl_;
};
#endif // !__UISVGICON_H__
#include "UISvgIcon.h"
#include <UPGL/UPGLUtil.h>
#include <QtCore/QFile>
#include <QtCore/QPointer>
#include <QtGui/QPixmap>
#include <QtGui/QPainter>
#include <QtGui/QScreen>
#include <QtSvg/QSvgRenderer>
#include <QtXml/QDomDocument>
class UISvgIcon::Pimpl
{
public:
Pimpl(const QString &svgPath);
~Pimpl();
public:
void setSVGProperty(QDomElement &&elem, const QString &tagName, const QString &property, const QString &value);
QString SVGProperty(QDomElement &&elem, const QString &tagName, const QString &property);
public:
QScopedPointer<QDomDocument> mSvgDoc_;
QScopedPointer<QSvgRenderer> pSvgRender_;
QScopedPointer<QPixmap> pPixmap_;
QPixmap mEmptyMap_;
QString mSvgPath_ = "";
};
UISvgIcon::Pimpl::Pimpl(const QString &svgPath)
{
mSvgPath_ = svgPath;
mSvgDoc_.reset(new QDomDocument());
QFile tFile(mSvgPath_);
tFile.open(QIODevice::ReadOnly | QFile::Text);
mSvgDoc_->setContent(&tFile);
tFile.close();
pSvgRender_.reset(new QSvgRenderer(mSvgDoc_->toByteArray()));
auto tDpi = UPGLUtil::getScreen()->logicalDotsPerInch();
pPixmap_.reset(new QPixmap(SVGProperty(mSvgDoc_->documentElement(), "svg", "width").toInt() * tDpi,
SVGProperty(mSvgDoc_->documentElement(), "svg", "height").toInt() * tDpi));
pPixmap_->fill(Qt::transparent);
QPainter tPainter(pPixmap_.get());
pSvgRender_->render(&tPainter);
}
UISvgIcon::Pimpl::~Pimpl()
{
}
void UISvgIcon::Pimpl::setSVGProperty(QDomElement &&elem, const QString &tagName, const QString &property, const QString &value)
{
if (elem.tagName().compare(tagName) == 0)
{
elem.setAttribute(property, value);
}
for (int i = 0; i < elem.childNodes().count(); i++)
{
if (elem.childNodes().at(i).isElement())
{
setSVGProperty(elem.childNodes().at(i).toElement(), tagName, property, value);
}
}
}
QString UISvgIcon::Pimpl::SVGProperty(QDomElement &&elem, const QString &tagName, const QString &property)
{
if (elem.tagName().compare(tagName) == 0)
{
return elem.attribute(property);
}
QString tPropertyStr;
for (int i = 0; i < elem.childNodes().count(); i++)
{
if (elem.childNodes().at(i).isElement())
{
tPropertyStr = SVGProperty(elem.childNodes().at(i).toElement(), tagName, property);
if (!tPropertyStr.isEmpty())
{
return tPropertyStr;
}
}
}
return tPropertyStr;
}
UISvgIcon::UISvgIcon(const QString &svgPath)
: impl_(std::make_unique<Pimpl>(svgPath))
{
}
UISvgIcon::~UISvgIcon()
{
}
const QPixmap& UISvgIcon::pixmap()
{
if (!impl_->pPixmap_.isNull())
{
return *impl_->pPixmap_;
}
// NOTE 禁止返回临时变量的引用
return impl_->mEmptyMap_;
}
void UISvgIcon::setFill(const QString &targetName, const QString &color)
{
impl_->setSVGProperty(impl_->mSvgDoc_->documentElement(), targetName, "fill", color);
QPainter tPainter(impl_->pPixmap_.get());
impl_->pSvgRender_->load(impl_->mSvgDoc_->toByteArray());
impl_->pSvgRender_->render(&tPainter);
}
使用
QScopedPointer<UISvgIcon> pInfoSvg_;
pInfoSvg_.reset(new UISvgIcon(":/Resource/skins/default/app/IconWarn.svg"));
QToolButton* closeButton = new QToolButton;
closeButton->setIcon(*closeIcon->pixmap());