我正在尝试将一个名为Part的子类QGraphicsObject渲染到QGraphicsScene中。
我正在绘制一个简单的矩形以确保paint事件被正确调用。该矩形在场景中被绘制在适当的位置上。但QGraphicsSvgItem,即m_part_graphic,没有被绘制在场景上。请问应该采用什么正确的方法?
总之,我想将两个不同的QGraphicsSvgItems作为“Part”类的一部分绘制到QGraphicsScene上。
更新:
根据下面的建议,我启动了一个新项目,并从SVG的基本graphicsview渲染开始。
如果我删除
它崩溃并给了我以下信息:(MS Visual Studio Pro 2012)
输出窗口:
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 3f0730. Receiver '' (of type 'QGraphicsSvgItem') was created in thread 3ff0a0", file kernel\qcoreapplication.cpp, line 535 Debug Error!
Program: C:\QT\4.8.5\bin\QtCored4.dll Module: 4.8.5 File: global\qglobal.cpp Line: 2303
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 3f0730. Receiver '' (of type 'QGraphicsSvgItem') was created in thread 3ff0a0", file kernel\qcoreapplication.cpp, line 535
以及调用堆栈:
class Part : public QGraphicsObject {
Q_OBJECT;
public:
Part(std::map<std::string, std::string> data, QString part_svg_file);
void setSharedRenderer(QSvgRenderer *r);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const;
QGraphicsSvgItem* GetPartSvg();
QGraphicsSvgItem* GetTerminalsSvg();
private:
QGraphicsSvgItem *m_part_graphic;
QGraphicsSvgItem *m_terminal_graphic;
QSvgRenderer *m_svg_renderer;
QDialog *m_dialog;
std::map<std::string, std::string> m_data;
}; // class Part
这部分包含两个QGraphicsSvgItems。这两个项在Part构建时从同一个SVG文件生成:
Part::Part(std::map<std::string, std::string> data, QString part_svg_file)
: m_terminal_graphic(new QGraphicsSvgItem(part_svg_file)),
m_part_graphic(new QGraphicsSvgItem(part_svg_file)),
m_svg_renderer(new QSvgRenderer())
{
m_part_graphic->setElementId("part");
m_terminal_graphic->setElementId("terminals");
}
SVG文件中包含两个组,一个称为“part”,另一个称为“terminals”。
我想要将这两个项呈现到QGraphicsScene中,我将它们放在单独的QGraphicsSvgItems中,以便我可以在某些情况下关闭“terminals”组。
我认为正确的方法是在父QGraphicsObject类的绘制事件中呈现它们。 但是,这种方法不起作用。
void Part::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
painter->setPen(Qt::PenStyle::SolidLine);
painter->setPen(Qt::black);
painter->setBrush(Qt::SolidPattern);
painter->setBrush(Qt::black);
painter->drawRect(0, 0, 25, 25);
m_part_graphic->setSharedRenderer(m_svg_renderer);
m_svg_renderer->render(painter);
}
我正在绘制一个简单的矩形以确保paint事件被正确调用。该矩形在场景中被绘制在适当的位置上。但QGraphicsSvgItem,即m_part_graphic,没有被绘制在场景上。请问应该采用什么正确的方法?
总之,我想将两个不同的QGraphicsSvgItems作为“Part”类的一部分绘制到QGraphicsScene上。
更新:
根据下面的建议,我启动了一个新项目,并从SVG的基本graphicsview渲染开始。
m_svg_item = new QGraphicsSvgItem("C:\\Code\\QT_Testing\\QT_Testing\\Resources\\bubbles.svg");
m_svg_item->setFlags(QGraphicsItem::ItemClipsToShape);
m_svg_item->setZValue(0);
s->addItem(m_svg_item);
如果我删除
s->addItem(m_svg_item);
这行代码,它会编译并正常运行。显然此时不会绘制SVG。它崩溃并给了我以下信息:(MS Visual Studio Pro 2012)
输出窗口:
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 3f0730. Receiver '' (of type 'QGraphicsSvgItem') was created in thread 3ff0a0", file kernel\qcoreapplication.cpp, line 535 Debug Error!
Program: C:\QT\4.8.5\bin\QtCored4.dll Module: 4.8.5 File: global\qglobal.cpp Line: 2303
ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 3f0730. Receiver '' (of type 'QGraphicsSvgItem') was created in thread 3ff0a0", file kernel\qcoreapplication.cpp, line 535
以及调用堆栈:
msvcr110d.dll!_CrtIsValidHeapPointer(const void * pUserData=0x004a76b0) Line 2036 C++
msvcr110d.dll!_free_dbg_nolock(void * pUserData=0x004a76b0, int nBlockUse=0) Line 1322 C++
msvcr110d.dll!_free_dbg(void * pUserData=0x004a76b0, int nBlockUse=0) Line 1265 C++
msvcr110d.dll!operator delete(void * pUserData=0x004a76b0) Line 54 C++
QtGuid4.dll!QGradientBrushData::`scalar deleting destructor'(unsigned int) C++
QtGuid4.dll!QBrushDataPointerDeleter::deleteData(QBrushData * d=0x004a76b0) Line 247 C++
QtGuid4.dll!QBrushDataPointerDeleter::cleanup(QBrushData * d=0x004a76b0) Line 257 C++
QtGuid4.dll!QScopedPointer<QBrushData,QBrushDataPointerDeleter>::reset(QBrushData * other=0x00432f38) Line 149 C++
QtGuid4.dll!QBrush::operator=(const QBrush & b={...}) Line 636 C++
main.cpp:
#include "qt_testing.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QT_Testing w;
w.show();
return a.exec();
}
qt_testing.cpp:
#include "qt_testing.h"
#include "svgview.h"
#include <QtGui>
QT_Testing::QT_Testing(QWidget *parent)
: QMainWindow(parent),
m_view(new SvgView)
{
setCentralWidget(m_view);
setWindowTitle("SVG Viewer");
}
QT_Testing::~QT_Testing()
{
}
void QT_Testing::openFile(const QString &path) {
QString file_name;
}
void QT_Testing::setRenderer(QAction *action) {
}
svgview.cpp:
#include "svgview.h"
#include <qfile.h>
#include <QtGui>
#include <QtSvg\qgraphicssvgitem.h>
SvgView::SvgView(QWidget *parent)
: QGraphicsView(parent)
, m_renderer(Native)
, m_svg_item(0)
, m_background_item(0)
, m_outline_item(0)
{
setScene(new QGraphicsScene(this));
setTransformationAnchor(AnchorUnderMouse);
setDragMode(ScrollHandDrag);
setViewportUpdateMode(FullViewportUpdate);
QPixmap tile_pixmap(64, 64);
tile_pixmap.fill(Qt::white);
QPainter tile_painter(&tile_pixmap);
QColor color(220, 220, 220);
tile_painter.fillRect(0, 0, 32, 32, color);
tile_painter.fillRect(32, 32, 32,32, color);
tile_painter.end();
setBackgroundBrush(tile_pixmap);
QGraphicsScene *s = scene();
s->clear();
resetTransform();
m_svg_item = new QGraphicsSvgItem("C:\\Code\\QT_Testing\\QT_Testing\\Resources\\bubbles.svg");
m_svg_item->setFlags(QGraphicsItem::ItemClipsToShape);
m_svg_item->setCacheMode(QGraphicsItem::NoCache);
m_svg_item->setZValue(0);
/*m_background_item = new QGraphicsRectItem(QRect(0, 0, 300, 300));
m_background_item->setBrush(Qt::white);
m_background_item->setPen(Qt::NoPen);
m_background_item->setVisible(true);
m_background_item->setZValue(-1);*/
//s->addItem(m_background_item);
s->addItem(m_svg_item);
s->addEllipse(150, 150, 100, 100, QPen(Qt::black, Qt::PenStyle::SolidLine));
s->setSceneRect(-10, -10, 320, 320);
}
void SvgView::drawBackground(QPainter *p, const QRectF &) {
p->save();
p->resetTransform();
p->drawTiledPixmap(viewport()->rect(), backgroundBrush().texture());
p->restore();
}
void SvgView::paintEvent(QPaintEvent *event) {
QGraphicsView::paintEvent(event);
}
void SvgView::wheelEvent(QWheelEvent *event) {
qreal factor = qPow(1.2, event->delta() / 240.0);
scale(factor, factor);
event->accept();
}
main.cpp
文件,在场景中放置一个QGraphicsSvgItem
,最好在代码中内联包含SVG文件(参见QBuffer
!)。如果它崩溃了,那么这是Qt的一个bug,你已经准备好提交给bug跟踪器的测试用例了。如果它工作正常,那么你就可以更容易地找出你的代码出了什么问题。 - Kuba hasn't forgotten Monicamain()
函数,实例化场景的地方,真的是整个代码。 - Kuba hasn't forgotten Monica