将 QGraphicsColorizeEffect 应用到 QGraphicsSvgItem 的一部分(仅适用于 svg 本身)
Apply QGraphicsColorizeEffect to a part of a QGraphicsSvgItem (only to the svg itself)
我有一个 QGraphicsSvgItem
subclass,我想在其中修改 svg 颜色。我想用它 QGraphicsColorizeEffect
,效果很好。
我的项目也有一个自定义选择矩形,突出显示 - 类似于其他项目类型。
当我应用着色效果时,高光也变成相同的颜色...
我试过setEnabled(false);
画图,但似乎没有效果。
示例代码:
file mysvg.h
#ifndef MYSVG_H
#define MYSVG_H
#include <QGraphicsSvgItem>
#include <QGraphicsColorizeEffect>
class MySvg : public QGraphicsSvgItem
{
public:
MySvg();
~MySvg();
virtual void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget = NULL);
private:
QGraphicsColorizeEffect* m_effect;
void drawSelectionRectangle(QPainter* painter, const QStyleOptionGraphicsItem* option, const QRectF& rectangle);
};
#endif // MYSVG_H
file mysvg.cpp
#include <QStyleOptionGraphicsItem>
#include <QStyle>
#include <QPainterPath>
#include <QPainter>
#include <QFileDialog>
#include <QSvgRenderer>
MySvg::MySvg()
{
m_effect = new QGraphicsColorizeEffect();
m_effect->setColor(Qt::red);
setGraphicsEffect(m_effect);
setFlags(QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable |
QGraphicsItem::ItemIsSelectable);
QString filename = QFileDialog::getOpenFileName(0, tr("Open Svg File"),
QString(), tr("Svg files (*.svg *.svgz)"));
setSharedRenderer(new QSvgRenderer(filename));
}
MySvg::~MySvg()
{
delete renderer();
delete m_effect;
}
void MySvg::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QStyleOptionGraphicsItem opt(*option);
opt.state = QStyle::State_None;
QGraphicsSvgItem::paint(painter, &opt, widget);
//m_effect->setEnabled(false); // no effect though seemed logical
QRectF rectangle = boundingRect();
if (option->state & (QStyle::State_Selected))
drawSelectionRectangle(painter, option, rectangle);
//m_effect->setEnabled(true);
}
void MySvg::drawSelectionRectangle(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRectF &rectangle)
{
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine));
painter->setBrush(QColor(255, 188, 0, 50));
painter->drawRect(rectangle);
}
file main.cpp
#include <QApplication>
#include <QGraphicsView>
#include "mysvg.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene s;
QGraphicsView view;
view.setScene(&s);
s.setSceneRect(-50, -50, 500, 650);
view.show();
MySvg* svg = new MySvg();
s.addItem(svg);
return app.exec();
}
file mysvg.pro
QT += core gui svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = mysvg
TEMPLATE = app
SOURCES += main.cpp \
mysvg.cpp
HEADERS += mysvg.h
我考虑过让 QGraphicsSvgItem
成为 MySvg
项的私有成员 - 但是 MySvg
项必须做很多其他事情,我不知道如何处理渲染器(谁会拥有它......) - 如果我能弄清楚如何使 QGraphicsSvgItem
subclass 成为 MySvg
class 的成员,我可以对成员应用着色并对 MySvg
项执行所有其他操作...
请帮我想办法将颜色应用到 svg,而不是项目的其他绘图部分。
Edit - 我试图将成员项目添加到 class 并将着色效果应用于成员 - 但它不应用着色效果完全... svg 加载了所有原始颜色。
这是包含会员项目的代码:
new mysvg.h
class SvgMember : public QGraphicsSvgItem
{
public:
SvgMember (const QByteArray &content, const QColor& c);
~SvgMember ();
private:
QGraphicsColorizeEffect* m_effect;
};
class MySvg : public QGraphicsItem
{
public:
MySvg();
~MySvg();
virtual void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget = NULL);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const;
private:
void drawSelectionRectangle(QPainter* painter, const QStyleOptionGraphicsItem* option, const QRectF& rectangle);
SvgMember * m_member;
};
new mysvg.cpp
MySvg::MySvg()
{
setFlags(QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable |
QGraphicsItem::ItemIsSelectable);
QString filename = QFileDialog::getOpenFileName(0, QObject::tr("Open Svg File"),
QString(), QObject::tr("Svg files (*.svg *.svgz)"));
QFile f(filename);
f.open(QFile::ReadOnly | QFile::Text);
QByteArray svgContents = f.readAll();
f.close();
m_member = new SvgMember (svgContents, Qt::red);
}
MySvg::~MySvg()
{
delete m_member;
}
void MySvg::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QStyleOptionGraphicsItem opt(*option);
opt.state = QStyle::State_None;
m_member->paint(painter, &opt, widget);
QRectF rectangle = boundingRect();
if (option->state & (QStyle::State_Selected))
drawSelectionRectangle(painter, option, rectangle);
}
/*! \brief reimplemented to use member rectangle */
QRectF MySvg::boundingRect() const
{
return m_member->boundingRect();
}
/*! \brief reimplemented to use member shape */
QPainterPath MySvg::shape() const
{
return m_member->shape();
}
void MySvg::drawSelectionRectangle(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRectF &rectangle)
{
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine));
painter->setBrush(QColor(255, 188, 0, 50));
painter->drawRect(rectangle);
}
SvgMember ::SvgMember (const QByteArray &content, const QColor &c)
{
m_effect = new QGraphicsColorizeEffect();
setGraphicsEffect(m_effect);
m_effect->setColor(c);
setSharedRenderer(new QSvgRenderer(content));
}
SvgMember ::~SvgMember ()
{
delete renderer();
delete m_effect;
}
如何将着色效果应用到 svg,而不是选择矩形?
该效果是基础 class QGraphicsItem
的一个特征。它应用于整个图形项及其所有子项。因此,项目内部绘制的所有内容都会受到其效果的影响。
选择矩形应该绘制在 SVG 项目对象之外。
它可以通过复合 class QGraphicsItemGroup
.
包围 QGraphicsSvgItem
来实现
当 QGraphicsItem
添加到 QGraphicsItemGroup
时,它会重新设置父级。因此,当组对象被销毁时,该项目也被销毁。因此,不需要手动删除它。 QGraphicsItem
拥有效果的所有权,因此不需要删除效果对象。
下面的 class MyGraphicsItemGroup
如您所愿。
Implementation "mygraphicsitemgroup.cpp"
#include "mygraphicsitemgroup.h"
#include <QGraphicsColorizeEffect>
#include <QGraphicsSvgItem>
#include <QStyleOptionGraphicsItem>
#include <QPainter>
#include <QFileDialog>
MyGraphicsItemGroup::MyGraphicsItemGroup()
{
setFlags(QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable |
QGraphicsItem::ItemIsSelectable);
QString filename = QFileDialog::getOpenFileName(0,
QObject::tr("Open Svg File"), QString(),
QObject::tr("Svg files (*.svg *.svgz)"));
QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect();
effect->setColor(Qt::red);
QGraphicsSvgItem *svg = new QGraphicsSvgItem(filename);
svg->setGraphicsEffect(effect);
addToGroup(svg);
}
void MyGraphicsItemGroup::paint(QPainter* painter,
const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QStyleOptionGraphicsItem opt(*option);
opt.state = QStyle::State_None;
QGraphicsItemGroup::paint(painter, &opt, widget);
QRectF rectangle = boundingRect();
if (option->state & QStyle::State_Selected)
drawSelectionRectangle(painter, option, rectangle);
}
void MyGraphicsItemGroup::drawSelectionRectangle(QPainter *painter,
const QStyleOptionGraphicsItem *option, const QRectF &rectangle)
{
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine));
painter->setBrush(QColor(255, 188, 0, 50));
painter->drawRect(rectangle);
}
Header "mygraphicsitemgroup.h"
#ifndef MYGRAPHICSITEMGROUP_H
#define MYGRAPHICSITEMGROUP_H
#include <QGraphicsItemGroup>
class MyGraphicsItemGroup : public QGraphicsItemGroup
{
public:
MyGraphicsItemGroup();
virtual void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option, QWidget* widget);
void drawSelectionRectangle(QPainter *painter,
const QStyleOptionGraphicsItem *option, const QRectF &rectangle);
};
#endif // MYGRAPHICSITEMGROUP_H
我有一个 QGraphicsSvgItem
subclass,我想在其中修改 svg 颜色。我想用它 QGraphicsColorizeEffect
,效果很好。
我的项目也有一个自定义选择矩形,突出显示 - 类似于其他项目类型。
当我应用着色效果时,高光也变成相同的颜色...
我试过setEnabled(false);
画图,但似乎没有效果。
示例代码:
file mysvg.h
#ifndef MYSVG_H
#define MYSVG_H
#include <QGraphicsSvgItem>
#include <QGraphicsColorizeEffect>
class MySvg : public QGraphicsSvgItem
{
public:
MySvg();
~MySvg();
virtual void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget = NULL);
private:
QGraphicsColorizeEffect* m_effect;
void drawSelectionRectangle(QPainter* painter, const QStyleOptionGraphicsItem* option, const QRectF& rectangle);
};
#endif // MYSVG_H
file mysvg.cpp
#include <QStyleOptionGraphicsItem>
#include <QStyle>
#include <QPainterPath>
#include <QPainter>
#include <QFileDialog>
#include <QSvgRenderer>
MySvg::MySvg()
{
m_effect = new QGraphicsColorizeEffect();
m_effect->setColor(Qt::red);
setGraphicsEffect(m_effect);
setFlags(QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable |
QGraphicsItem::ItemIsSelectable);
QString filename = QFileDialog::getOpenFileName(0, tr("Open Svg File"),
QString(), tr("Svg files (*.svg *.svgz)"));
setSharedRenderer(new QSvgRenderer(filename));
}
MySvg::~MySvg()
{
delete renderer();
delete m_effect;
}
void MySvg::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QStyleOptionGraphicsItem opt(*option);
opt.state = QStyle::State_None;
QGraphicsSvgItem::paint(painter, &opt, widget);
//m_effect->setEnabled(false); // no effect though seemed logical
QRectF rectangle = boundingRect();
if (option->state & (QStyle::State_Selected))
drawSelectionRectangle(painter, option, rectangle);
//m_effect->setEnabled(true);
}
void MySvg::drawSelectionRectangle(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRectF &rectangle)
{
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine));
painter->setBrush(QColor(255, 188, 0, 50));
painter->drawRect(rectangle);
}
file main.cpp
#include <QApplication>
#include <QGraphicsView>
#include "mysvg.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QGraphicsScene s;
QGraphicsView view;
view.setScene(&s);
s.setSceneRect(-50, -50, 500, 650);
view.show();
MySvg* svg = new MySvg();
s.addItem(svg);
return app.exec();
}
file mysvg.pro
QT += core gui svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = mysvg
TEMPLATE = app
SOURCES += main.cpp \
mysvg.cpp
HEADERS += mysvg.h
我考虑过让 QGraphicsSvgItem
成为 MySvg
项的私有成员 - 但是 MySvg
项必须做很多其他事情,我不知道如何处理渲染器(谁会拥有它......) - 如果我能弄清楚如何使 QGraphicsSvgItem
subclass 成为 MySvg
class 的成员,我可以对成员应用着色并对 MySvg
项执行所有其他操作...
请帮我想办法将颜色应用到 svg,而不是项目的其他绘图部分。
Edit - 我试图将成员项目添加到 class 并将着色效果应用于成员 - 但它不应用着色效果完全... svg 加载了所有原始颜色。
这是包含会员项目的代码:
new mysvg.h
class SvgMember : public QGraphicsSvgItem
{
public:
SvgMember (const QByteArray &content, const QColor& c);
~SvgMember ();
private:
QGraphicsColorizeEffect* m_effect;
};
class MySvg : public QGraphicsItem
{
public:
MySvg();
~MySvg();
virtual void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget = NULL);
virtual QRectF boundingRect() const;
virtual QPainterPath shape() const;
private:
void drawSelectionRectangle(QPainter* painter, const QStyleOptionGraphicsItem* option, const QRectF& rectangle);
SvgMember * m_member;
};
new mysvg.cpp
MySvg::MySvg()
{
setFlags(QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable |
QGraphicsItem::ItemIsSelectable);
QString filename = QFileDialog::getOpenFileName(0, QObject::tr("Open Svg File"),
QString(), QObject::tr("Svg files (*.svg *.svgz)"));
QFile f(filename);
f.open(QFile::ReadOnly | QFile::Text);
QByteArray svgContents = f.readAll();
f.close();
m_member = new SvgMember (svgContents, Qt::red);
}
MySvg::~MySvg()
{
delete m_member;
}
void MySvg::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QStyleOptionGraphicsItem opt(*option);
opt.state = QStyle::State_None;
m_member->paint(painter, &opt, widget);
QRectF rectangle = boundingRect();
if (option->state & (QStyle::State_Selected))
drawSelectionRectangle(painter, option, rectangle);
}
/*! \brief reimplemented to use member rectangle */
QRectF MySvg::boundingRect() const
{
return m_member->boundingRect();
}
/*! \brief reimplemented to use member shape */
QPainterPath MySvg::shape() const
{
return m_member->shape();
}
void MySvg::drawSelectionRectangle(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRectF &rectangle)
{
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine));
painter->setBrush(QColor(255, 188, 0, 50));
painter->drawRect(rectangle);
}
SvgMember ::SvgMember (const QByteArray &content, const QColor &c)
{
m_effect = new QGraphicsColorizeEffect();
setGraphicsEffect(m_effect);
m_effect->setColor(c);
setSharedRenderer(new QSvgRenderer(content));
}
SvgMember ::~SvgMember ()
{
delete renderer();
delete m_effect;
}
如何将着色效果应用到 svg,而不是选择矩形?
该效果是基础 class QGraphicsItem
的一个特征。它应用于整个图形项及其所有子项。因此,项目内部绘制的所有内容都会受到其效果的影响。
选择矩形应该绘制在 SVG 项目对象之外。
它可以通过复合 class QGraphicsItemGroup
.
QGraphicsSvgItem
来实现
当 QGraphicsItem
添加到 QGraphicsItemGroup
时,它会重新设置父级。因此,当组对象被销毁时,该项目也被销毁。因此,不需要手动删除它。 QGraphicsItem
拥有效果的所有权,因此不需要删除效果对象。
下面的 class MyGraphicsItemGroup
如您所愿。
Implementation "mygraphicsitemgroup.cpp"
#include "mygraphicsitemgroup.h"
#include <QGraphicsColorizeEffect>
#include <QGraphicsSvgItem>
#include <QStyleOptionGraphicsItem>
#include <QPainter>
#include <QFileDialog>
MyGraphicsItemGroup::MyGraphicsItemGroup()
{
setFlags(QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsFocusable |
QGraphicsItem::ItemIsSelectable);
QString filename = QFileDialog::getOpenFileName(0,
QObject::tr("Open Svg File"), QString(),
QObject::tr("Svg files (*.svg *.svgz)"));
QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect();
effect->setColor(Qt::red);
QGraphicsSvgItem *svg = new QGraphicsSvgItem(filename);
svg->setGraphicsEffect(effect);
addToGroup(svg);
}
void MyGraphicsItemGroup::paint(QPainter* painter,
const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QStyleOptionGraphicsItem opt(*option);
opt.state = QStyle::State_None;
QGraphicsItemGroup::paint(painter, &opt, widget);
QRectF rectangle = boundingRect();
if (option->state & QStyle::State_Selected)
drawSelectionRectangle(painter, option, rectangle);
}
void MyGraphicsItemGroup::drawSelectionRectangle(QPainter *painter,
const QStyleOptionGraphicsItem *option, const QRectF &rectangle)
{
painter->setPen(QPen(option->palette.windowText(), 0, Qt::DotLine));
painter->setBrush(QColor(255, 188, 0, 50));
painter->drawRect(rectangle);
}
Header "mygraphicsitemgroup.h"
#ifndef MYGRAPHICSITEMGROUP_H
#define MYGRAPHICSITEMGROUP_H
#include <QGraphicsItemGroup>
class MyGraphicsItemGroup : public QGraphicsItemGroup
{
public:
MyGraphicsItemGroup();
virtual void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option, QWidget* widget);
void drawSelectionRectangle(QPainter *painter,
const QStyleOptionGraphicsItem *option, const QRectF &rectangle);
};
#endif // MYGRAPHICSITEMGROUP_H