Qt SVG Viewer Example 看看看~

Qt提供在widgets和其他paint device上渲染和展示SVG的类,本例就允许用户载入SVG文件并在QGraphicsView上用QGraphicsSvgItem显示它。并且例子还可以选择渲染者,QGraphicsView可以用QWidgetQGLWidget作为视口。也可以使用第三方渲染模型通过QImage

 

程序运行如图:renderer可以选择:NativeOpenGLImage

程序的main函数:

int main(int argc, char **argv)

{

   Q_INIT_RESOURCE(svgviewer);


   QApplication app(argc, argv);


   MainWindow window;

   if (argc == 2)

       window.openFile(argv[1]);

   else

       window.openFile(":/files/bubbles.svg");

#if defined(Q_OS_SYMBIAN)

   window.showMaximized();

#else

   window.show();

#endif

   return app.exec();

}

允许窗传递参数给程序,用来打开任意svg文件。

 

程序使用子类化QGraphicsView来显示svg文件。这里使用到了Graphic Scene Framework。上一篇博客简单介绍了它。通过QGraphicsItemQGraphicsRectItem显示View中的svg文件内容和边框及背景。

 

本例由两个主要类组成:svgview,MainWindow 

 

class SvgView : public QGraphicsView
{
    Q_OBJECT

public:
    enum RendererType { Native, OpenGL, Image };

    SvgView(QWidget *parent = 0);

    void openFile(const QFile &file);
    void setRenderer(RendererType type = Native);
    void drawBackground(QPainter *p, const QRectF &rect);

public slots:       // 接收MainWindow菜单项信号的槽
    void setHighQualityAntialiasing(bool highQualityAntialiasing);
    void setViewBackground(bool enable);
    void setViewOutline(bool enable);

protected:         // 重写wheelEvent,paintEvent事件处理器
    void wheelEvent(QWheelEvent *event);
    void paintEvent(QPaintEvent *event);

private:
    RendererType m_renderer;                // 当前renderer

    QGraphicsItem *m_svgItem;               // svg文件内容渲染项
    QGraphicsRectItem *m_backgroundItem;    // background渲染
    QGraphicsRectItem *m_outlineItem;       // outline渲染

    QImage m_image;                         // 当前照片
};


SvgView::SvgView(QWidget *parent)
    : QGraphicsView(parent)
    , m_renderer(Native)
    , m_svgItem(0)
    , m_backgroundItem(0)
    , m_outlineItem(0)
{
    setScene(new QGraphicsScene(this));             // 创建并设置Scene
    setTransformationAnchor(AnchorUnderMouse);      // 设置鼠标点为锚点
    setDragMode(ScrollHandDrag);                    // 拖动模式:手型拖动
    setViewportUpdateMode(FullViewportUpdate);      // 视口更新模式:整个视口更新

    // Prepare background check-board pattern
    QPixmap tilePixmap(64, 64);
    tilePixmap.fill(Qt::white);                     // 白色背景
    QPainter tilePainter(&tilePixmap);
    QColor color(220, 220, 220);
    tilePainter.fillRect(0, 0, 32, 32, color);
    tilePainter.fillRect(32, 32, 32, 32, color);
    tilePainter.end();

    setBackgroundBrush(tilePixmap);
}

void SvgView::drawBackground(QPainter *p, const QRectF &)  // 绘制瓦片背景
{
    p->save();
    p->resetTransform();
    p->drawTiledPixmap(viewport()->rect(), backgroundBrush().texture());
    p->restore();
}

void SvgView::openFile(const QFile &file)  // 在svg view里打开svg文件
{
    if (!file.exists())
        return;

    QGraphicsScene *s = scene();           // 返回当前Scene的指针

    bool drawBackground = (m_backgroundItem ? m_backgroundItem->isVisible() : false);
    bool drawOutline = (m_outlineItem ? m_outlineItem->isVisible() : true);

    s->clear();
    resetTransform();                      // 重置view转换

    m_svgItem = new QGraphicsSvgItem(file.fileName());      // 用file初始化QGraphicsSvgItem
    m_svgItem->setFlags(QGraphicsItem::ItemClipsToShape);
    m_svgItem->setCacheMode(QGraphicsItem::NoCache);
    m_svgItem->setZValue(0);

    m_backgroundItem = new QGraphicsRectItem(m_svgItem->boundingRect()); // 设置背景项
    m_backgroundItem->setBrush(Qt::white);
    m_backgroundItem->setPen(Qt::NoPen);
    m_backgroundItem->setVisible(drawBackground);
    m_backgroundItem->setZValue(-1);

    m_outlineItem = new QGraphicsRectItem(m_svgItem->boundingRect());    // 设置边框项
    QPen outline(Qt::black, 2, Qt::DashLine);
    outline.setCosmetic(true);
    m_outlineItem->setPen(outline);
    m_outlineItem->setBrush(Qt::NoBrush);
    m_outlineItem->setVisible(drawOutline);
    m_outlineItem->setZValue(1);

    s->addItem(m_backgroundItem);                   // 将svg内容,边框,背景添加到Scene
    s->addItem(m_svgItem);
    s->addItem(m_outlineItem);

    s->setSceneRect(m_outlineItem->boundingRect().adjusted(-10, -10, 10, 10));
}

void SvgView::setRenderer(RendererType type)       // 选择renderer设置视口
{
    m_renderer = type;

    if (m_renderer == OpenGL) {
#ifndef QT_NO_OPENGL
        setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
#endif
    } else {
        setViewport(new QWidget);
    }
}

void SvgView::setHighQualityAntialiasing(bool highQualityAntialiasing)  // 高质量反走样 槽
{
#ifndef QT_NO_OPENGL
    setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
#else
    Q_UNUSED(highQualityAntialiasing);
#endif
}

void SvgView::setViewBackground(bool enable)        // 设置背景 槽
{
    if (!m_backgroundItem)
          return;

    m_backgroundItem->setVisible(enable);
}

void SvgView::setViewOutline(bool enable)           // 设置outline 槽
{
    if (!m_outlineItem)
        return;

    m_outlineItem->setVisible(enable);
}

void SvgView::paintEvent(QPaintEvent *event)        // 选择Image时,将view内容以图片形式绘制出来,通过viewport()
{
    if (m_renderer == Image) {
        if (m_image.size() != viewport()->size()) {
            m_image = QImage(viewport()->size(), QImage::Format_ARGB32_Premultiplied);
        }

        QPainter imagePainter(&m_image);
        QGraphicsView::render(&imagePainter);
        imagePainter.end();

        QPainter p(viewport());
        p.drawImage(0, 0, m_image);

    } else {
        QGraphicsView::paintEvent(event);
    }
}

void SvgView::wheelEvent(QWheelEvent *event)
{
    qreal factor = qPow(1.2, event->delta() / 240.0);
    scale(factor, factor);              // 伸缩view
    event->accept();                    // accept()事件
}


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow();

public slots:
    void openFile(const QString &path = QString()); // 打开文件槽
    void setRenderer(QAction *action);              // 设置renderer槽

private:
    QAction *m_nativeAction;                    //用于菜单项的动作
    QAction *m_glAction;
    QAction *m_imageAction;
    QAction *m_highQualityAntialiasingAction;
    QAction *m_backgroundAction;
    QAction *m_outlineAction;

    SvgView *m_view;                            // MainWindow中心的View部件

    QString m_currentPath;                      // open file时的路径
};


MainWindow::MainWindow()
    : QMainWindow()
    , m_view(new SvgView)
{
    QMenu *fileMenu = new QMenu(tr("&File"), this);               // 创建file菜单
    QAction *openAction = fileMenu->addAction(tr("&Open..."));    // 添加open菜单项
    openAction->setShortcut(QKeySequence(tr("Ctrl+O")));          // 快捷键
    QAction *quitAction = fileMenu->addAction(tr("E&xit"));       // 添加Exit菜单项
    quitAction->setShortcuts(QKeySequence::Quit);                 // 快捷键

    menuBar()->addMenu(fileMenu);                                 // 添加到菜单栏

    QMenu *viewMenu = new QMenu(tr("&View"), this);               // 创建view菜单
    m_backgroundAction = viewMenu->addAction(tr("&Background"));  // 添加背景菜单项
    m_backgroundAction->setEnabled(true);                        // 设置不可用
    m_backgroundAction->setCheckable(true);                       // 设置可打勾选择
    m_backgroundAction->setChecked(false);                        // 初始化不打勾
    // 设置信号槽,背景动作激发m_view成员的槽setViewBackground
    connect(m_backgroundAction, SIGNAL(toggled(bool)), m_view, SLOT(setViewBackground(bool)));

    m_outlineAction = viewMenu->addAction(tr("&Outline"));        // 添加菜单项:外围包围线
    m_outlineAction->setEnabled(false);                           // 设置不可用
    m_outlineAction->setCheckable(true);                          // 设置可打勾选择
    m_outlineAction->setChecked(true);                            // 初始化打勾
    // 设置信号槽,包围线触发m_view成员的槽setViewOutline
    connect(m_outlineAction, SIGNAL(toggled(bool)), m_view, SLOT(setViewOutline(bool)));

    menuBar()->addMenu(viewMenu);                                 // 将view菜单添加到菜单栏

    QMenu *rendererMenu = new QMenu(tr("&Renderer"), this);       // 创建Renderer菜单
    m_nativeAction = rendererMenu->addAction(tr("&Native"));      // 添加Native菜单项
    m_nativeAction->setCheckable(true);                           // 设置可打勾选择
    m_nativeAction->setChecked(true);                             // 初始化打勾
#ifndef QT_NO_OPENGL     // 如果定义了QT_NO_OPENGL就不添加OPNGL相关的菜单项
    m_glAction = rendererMenu->addAction(tr("&OpenGL"));          // 添加OpenGL菜单项
    m_glAction->setCheckable(true);                               // 设置可打勾选择
#endif
    m_imageAction = rendererMenu->addAction(tr("&Image"));        // 添加Image菜单项
    m_imageAction->setCheckable(true);                            // 设置可打勾选择

#ifndef QT_NO_OPENGL
    rendererMenu->addSeparator();                                 // 添加分隔线
    // 添加高质量反走样菜单项
    m_highQualityAntialiasingAction = rendererMenu->addAction(tr("&High Quality Antialiasing"));
    m_highQualityAntialiasingAction->setEnabled(false);
    m_highQualityAntialiasingAction->setCheckable(true);
    m_highQualityAntialiasingAction->setChecked(false);
    // 添加信号槽,触发m_view的setHightQualityAntialasing
    connect(m_highQualityAntialiasingAction, SIGNAL(toggled(bool)), m_view, SLOT(setHighQualityAntialiasing(bool)));
#endif

    // 将native,opengl,image菜单项组合在一起(每次只选择其中的一个)
    QActionGroup *rendererGroup = new QActionGroup(this);
    rendererGroup->addAction(m_nativeAction);
#ifndef QT_NO_OPENGL
    rendererGroup->addAction(m_glAction);
#endif
    rendererGroup->addAction(m_imageAction);

    menuBar()->addMenu(rendererMenu);                           // renderer菜单添加到菜单栏

    connect(openAction, SIGNAL(triggered()), this, SLOT(openFile())); // openAction连接槽openFile
    connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));     // quitAction连接到quit槽
    connect(rendererGroup, SIGNAL(triggered(QAction*)),
            this, SLOT(setRenderer(QAction*)));                       // rendererGroup连接到setRender槽

    setCentralWidget(m_view);           // 将svg view窗体部件放置MainWindow中心
    setWindowTitle(tr("SVG Viewer"));   // 标题
}

void MainWindow::openFile(const QString &path)
{
    QString fileName;
    if (path.isNull())                 // FileDialog获得路径
        fileName = QFileDialog::getOpenFileName(this, tr("Open SVG File"),
                m_currentPath, "SVG files (*.svg *.svgz *.svg.gz)");
    else
        fileName = path;

    if (!fileName.isEmpty()) {         // 处理获得的文件路径
        QFile file(fileName);
        if (!file.exists()) {          // 文件不存在:弹出MessageBox提示
            QMessageBox::critical(this, tr("Open SVG File"),
                           QString("Could not open file '%1'.").arg(fileName));

            m_outlineAction->setEnabled(false);                    // outline,background菜单项不可用
            m_backgroundAction->setEnabled(false);
            return;
        }

        m_view->openFile(file);                  // 将文件在svg view上打开

        if (!fileName.startsWith(":/")) {        // 更改窗体标题
            m_currentPath = fileName;
            setWindowTitle(tr("%1 - SVGViewer").arg(m_currentPath));
        }

        m_outlineAction->setEnabled(true);       // 是菜单项outline,background可用
        m_backgroundAction->setEnabled(true);

        resize(m_view->sizeHint() + QSize(80, 80 + menuBar()->height()));
    }
}

void MainWindow::setRenderer(QAction *action)    //setRenderer槽
{
#ifndef QT_NO_OPENGL
    m_highQualityAntialiasingAction->setEnabled(false);
#endif

    // 将当前renderer设置为菜单中选择的
    if (action == m_nativeAction)
        m_view->setRenderer(SvgView::Native);
#ifndef QT_NO_OPENGL
    else if (action == m_glAction) {
        m_highQualityAntialiasingAction->setEnabled(true);
        m_view->setRenderer(SvgView::OpenGL);
    }
#endif
    else if (action == m_imageAction) {
        m_view->setRenderer(SvgView::Image);
    }
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值