QGraphicsSvgItem crash when rendering into pixmap
-
Hi,
How are you creating the new item on the scene ?
-
Even when you find the bug inside Qt, you may not be able to fix it. But you can file a bug or try a newer version of Qt. How about create QGraphicsItem with svg image? Instead of using QGraphicsSvgItem. Whenever the size of image is changed, simply create it from your svg file and the resolution of your image will not be affected. .
-
@JonB said in QGraphicsSvgItem crash when rendering into pixmap:
It would be helpful if you have Qt 5.15 compiled from source and you let it "crash" under the debugger?
That is true. However, that would come with quite a sizable time investment which I'd like to avoid in case this is a "common issue" or something else that someone more knowledgeable than me can point me towards :)
@SGaist said in QGraphicsSvgItem crash when rendering into pixmap:
How are you creating the new item on the scene ?
The
QGraphicsSvgItem
is simply a member of anotherQGraphicsObject
. Roughly like this:class foo : public QGraphicsObject { public: void set_icon_path(const QString& path) { if (m_svg_item) delete m_svg_item; m_icon_filepath = filepath; if (m_icon_filepath.isEmpty() || !QFileInfo::exists(filepath)) return; m_svg_item = new QGraphicsSvgItem(m_icon_filepath, this); m_svg_item->setPos(ICON_PADDING, ICON_PADDING); } private: QGraphicsSvgItem* m_svg_item = nullptr; QString m_icon_filepath; };
That's pretty much everything related to the
QGraphicsSvgItem
in my code base. I simply create the item and set the parent accordingly in the constructor.@JoeCFD said in QGraphicsSvgItem crash when rendering into pixmap:
Even when you find the bug inside Qt, you may not be able to fix it. But you can file a bug or try a newer version of Qt. How about create QGraphicsItem with svg image? Instead of using QGraphicsSvgItem. Whenever the size of image is changed, simply create it from your svg file and the resolution of your image will not be affected. .
I'm not necessarily expecting a bug in Qt. I started looking at the
QGraphicsSvgItem
implementation in hopes of figuring out whether I am missing something crucial that I also missed when reading the docs.
Your workaround of course makes sense but I'd much rather not do that. After all,QGraphicsSvgItem
is working well within theQGraphicsScene
. My issue is solely related to rendering it outside of a scene. -
One maybe silly question... Why do you need that class at all ? It seems to be a wrapper that reduces the QGraphicsSvgItem API.
-
@SGaist said in QGraphicsSvgItem crash when rendering into pixmap:
One maybe silly question... Why do you need that class at all ? It seems to be a wrapper that reduces the QGraphicsSvgItem API.
Not a silly question by any means. The
foo
class above is just an excerpt that shows everything related to the handling of theQGraphicsSvgItem
. In the actual application, the classfoo
first of all isn't namedfoo
and secondly contains a whole lot more code (which is 100% unrelated to the SVG item hence not shown here) :) -
Ok, then another comprehension question. Is your goal to update the QDrag pixmap while you are moving over the scene ?
-
@SGaist said in QGraphicsSvgItem crash when rendering into pixmap:
Is your goal to update the QDrag pixmap while you are moving over the scene ?
Nope. The
QDrag
pixmap gets generated when the drag starts (inQTreeView::startDrag()
) and never changes afterwards. -
In that case, why not simply load the file in a QPixmap ? The QtSvg module provides an image format plugin so there's no need for that item.
-
Looking at these questions I think it is reasonable that I provide some background information not given in the original post as I deemed it "out of scope" - so where we go :)
I have an application using the Qt Graphics Framework. In that application, a user can create a flowchart-like diagram. Here's a screenshot of the application:
This is done using the open-source QSchematic library (disclaimer: I'm the author).In the screenshot above, the blocks with the blue header and the white body is based on the
QSchematic::Node
class (which itself inherits fromQGraphicsObject
). Each node can have zero or more connectors. A connector (QSchematic::Connector
) inherits fromQGraphicsItem
. These connectors are children of theQSchematic::Node
. Nothing special here.Those nodes can also have an icon. In the screenshot above, only the top-left node shows an icon. As of now, I simply keep a
QIcon
inside my node class and paint that manually in the node'spaint()
override. The problem here is that when the user zooms in, the icons don't look pretty. The icons themselves (the resources/assets) are SVGs but as I load them into aQIcon
they get rasterized and end up looking unpleasant when zooming into the scene.
To solve this issue, I decided to add another child item to the node class - the aforementionedQGraphicsSvgItem
.As mentioned in the opening post the
QGraphicsSvgItem
works just fine inside the scene. The part where my application crashes is when I render a preview of the node using thetoPixmap()
function shown in my opening post.
The reason why I am using thistoPixmap()
function is to render the node before it actually becomes part of the scene. There is an item library built around aQTreeView
from which the user can drag an node and drop it onto the scene/view. To make things look nice and to provide the user with a visual reference of where the block will be placed, I render the block into aQPixmap
and assign that to theQDrag
object. Here is a video of that in action: https://www.veed.io/view/4d2b2da8-3016-4b26-b55f-ea27db793f98The summary of this is still: I have a custom graphics item composed of several child items, everything works fine inside the scene but when I render it outside the scene using the
toPixmap()
function shown in the opening post, the application crashes onceQGraphicsSvgItem::paint()
is called. The crash is caused by a seg fault.@SGaist said in QGraphicsSvgItem crash when rendering into pixmap:
In that case, why not simply load the file in a QPixmap ? The QtSvg module provides an image format plugin so there's no need for that item.
I wasn't aware that
QPixmap
can gain SVG support viaQtSVG
- that's good intel, thank you!
However, would this still raster the image? Or can I "assign" an SVG image to aQPixmap
, render theQPixmap
in aQGraphicsItem
and it won't look "pixelated" when the user zooms in?
The reason why I choiceQGraphicsSvgItem
is two fold: I didn't know thatQPixmap
can receive SVG support and it just handles all the scaling and stuff automatically. -
To show the SVG on the scene, the item is the right tool.
I would simply use the pixmap for the drag image rendering. In case the result is not what you expect, there's also the QSvgRenderer class that might be of interest. -
It has been a while but I'm an advocate for posting the solution even if a long time has passed...
The problem was that in
QSchematic::Items::Item::toPixmap()
(snipped shown in the opening post here) where I render theQGraphicsItem
into aQPixmap
I passednullptr
for theQStyleOptionGraphicsItem
parameter.
When I create a default-constructedQStyleOptionGraphicsItem
and pass a pointer to that instead everything works as expected.I assume (!) that
QGraphicsSvgItem
requiresQStyleOptionGraphicsItem
to be non-null.QSchematic upstream commits fixing this:
-
J Joel Bodenmann has marked this topic as solved on
-
@Joel-Bodenmann said in QGraphicsSvgItem crash when rendering into pixmap:
I assume (!) that
QGraphicsSvgItem
requiresQStyleOptionGraphicsItem
to be non-null.That is correct. Beyond that, the documentation doesn't suggest that anything other than a valid object is expected.