【问题标题】:QSvgRenderer painting problemsQSvgRenderer 绘制问题
【发布时间】:2014-04-08 22:48:36
【问题描述】:

我正在尝试将名为 Part 的子类 QGraphicsObject 渲染到 QGraphicsScene。

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

这部分包含两个 QGraphicsSvgItem。这两项是在构建 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 包含两个组,因此有两个项目,一个称为“部分”,另一个称为“终端”

我希望将这两个项目呈现到 QGraphicsScene,我将它们放在单独的 QGraphicsSvgItems 中,以允许我在某些情况下关闭“终端”组。

虽然正确的方法是在我的父 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);
}

我正在绘制一个简单的矩形以确保正确调用绘制事件。矩形正在场景中的适当位置绘制。 QGraphicsSvgItem,m_part_graphic,没有被绘制在场景中。这样做的正确方法是什么?

回顾一下,我想将两个不同的 QGraphicsSvgItem 绘制到 QGraphicsScene 上,作为名为“Part”的更大类的一部分。


更新

根据下面的建议,我开始了一个新项目,并从 SVG 的基本图形视图渲染开始。

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-&gt;addItem(m_svg_item); 行,它会编译并运行良好。显然那时也没有绘制 SVG。

它崩溃并给了我以下信息:(MS Visual Studio Pro 2012)

输出窗口:

QCoreApplication::sendEvent 中的 ASSERT 失败:“无法将事件发送到 由不同线程拥有的对象。当前线程 3f0730。接收者 '' ('QGraphicsSvgItem' 类型) 是在线程 3ff0a0 中创建的",文件 kernel\qcoreapplication.cpp,第 535 行调试错误!

程序:C:\QT\4.8.5\bin\QtCored4.dll 模块:4.8.5 文件: global\qglobal.cpp 行:2303

QCoreApplication::sendEvent 中的 ASSERT 失败:“无法将事件发送到 由不同线程拥有的对象。当前线程 3f0730。接收者 '' ('QGraphicsSvgItem' 类型) 是在线程 3ff0a0 中创建的",文件 kernel\qcoreapplication.cpp,第 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();
}

【问题讨论】:

  • 子项可能是您的项的子项并自己绘制。您根本不需要做任何特别的事情来绘制它们 - 只需确保它们实际上是您项目的子项。
  • 我将我的构造函数初始化列表更改为: : m_terminal_graphic(new QGraphicsSvgItem(part_svg_file, this)), m_part_graphic(new QGraphicsSvgItem(part_svg_file, this)),
  • 现在程序因“_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)而崩溃
  • 这真令人气愤。无论我如何尝试使用 QGraphicsSvgItem 类绘制 svg 项目,它都会崩溃。我尝试在图形场景构造函数中生成 svgitem 并将其添加到场景中。这也会崩溃。
  • 按照本教程:qt-project.org/doc/qt-4.8/painting-svgviewer-svgview-cpp.html,我也遇到了崩溃。专门看openFile函数。

标签: qt svg


【解决方案1】:

尽管我讨厌这个答案,但这是我为解决这个问题所做的。由于 Visual Studio 2012 不正式支持 QT 4.8.5,我完全擦除了我的 QT 安装并安装了 QT 5.2.1。在修复了一些包含路径之后,上面的代码编译并运行得很好。 SVG 现在按预期绘制。感谢 Kuba Ober 的帮助。非常感谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    相关资源
    最近更新 更多