Qt SVG Viewer Demo 解读

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。上一篇博客简单介绍了它。通过QGraphicsItem,QGraphicsRectItem显示View中的svg文件内容和边框及背景。

 

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

 

[cpp]  view plain copy
  1. class SvgView : public QGraphicsView  
  2. {  
  3.     Q_OBJECT  
  4.   
  5. public:  
  6.     enum RendererType { Native, OpenGL, Image };  
  7.   
  8.     SvgView(QWidget *parent = 0);  
  9.   
  10.     void openFile(const QFile &file);  
  11.     void setRenderer(RendererType type = Native);  
  12.     void drawBackground(QPainter *p, const QRectF &rect);  
  13.   
  14. public slots:       // 接收MainWindow菜单项信号的槽  
  15.     void setHighQualityAntialiasing(bool highQualityAntialiasing);  
  16.     void setViewBackground(bool enable);  
  17.     void setViewOutline(bool enable);  
  18.   
  19. protected:         // 重写wheelEvent,paintEvent事件处理器  
  20.     void wheelEvent(QWheelEvent *event);  
  21.     void paintEvent(QPaintEvent *event);  
  22.   
  23. private:  
  24.     RendererType m_renderer;                // 当前renderer  
  25.   
  26.     QGraphicsItem *m_svgItem;               // svg文件内容渲染项  
  27.     QGraphicsRectItem *m_backgroundItem;    // background渲染  
  28.     QGraphicsRectItem *m_outlineItem;       // outline渲染  
  29.   
  30.     QImage m_image;                         // 当前照片  
  31. };  


[cpp]  view plain copy
  1. SvgView::SvgView(QWidget *parent)  
  2.     : QGraphicsView(parent)  
  3.     , m_renderer(Native)  
  4.     , m_svgItem(0)  
  5.     , m_backgroundItem(0)  
  6.     , m_outlineItem(0)  
  7. {  
  8.     setScene(new QGraphicsScene(this));             // 创建并设置Scene  
  9.     setTransformationAnchor(AnchorUnderMouse);      // 设置鼠标点为锚点  
  10.     setDragMode(ScrollHandDrag);                    // 拖动模式:手型拖动  
  11.     setViewportUpdateMode(FullViewportUpdate);      // 视口更新模式:整个视口更新  
  12.   
  13.     // Prepare background check-board pattern  
  14.     QPixmap tilePixmap(64, 64);  
  15.     tilePixmap.fill(Qt::white);                     // 白色背景  
  16.     QPainter tilePainter(&tilePixmap);  
  17.     QColor color(220, 220, 220);  
  18.     tilePainter.fillRect(0, 0, 32, 32, color);  
  19.     tilePainter.fillRect(32, 32, 32, 32, color);  
  20.     tilePainter.end();  
  21.   
  22.     setBackgroundBrush(tilePixmap);  
  23. }  
  24.   
  25. void SvgView::drawBackground(QPainter *p, const QRectF &)  // 绘制瓦片背景  
  26. {  
  27.     p->save();  
  28.     p->resetTransform();  
  29.     p->drawTiledPixmap(viewport()->rect(), backgroundBrush().texture());  
  30.     p->restore();  
  31. }  
  32.   
  33. void SvgView::openFile(const QFile &file)  // 在svg view里打开svg文件  
  34. {  
  35.     if (!file.exists())  
  36.         return;  
  37.   
  38.     QGraphicsScene *s = scene();           // 返回当前Scene的指针  
  39.   
  40.     bool drawBackground = (m_backgroundItem ? m_backgroundItem->isVisible() : false);  
  41.     bool drawOutline = (m_outlineItem ? m_outlineItem->isVisible() : true);  
  42.   
  43.     s->clear();  
  44.     resetTransform();                      // 重置view转换  
  45.   
  46.     m_svgItem = new QGraphicsSvgItem(file.fileName());      // 用file初始化QGraphicsSvgItem  
  47.     m_svgItem->setFlags(QGraphicsItem::ItemClipsToShape);  
  48.     m_svgItem->setCacheMode(QGraphicsItem::NoCache);  
  49.     m_svgItem->setZValue(0);  
  50.   
  51.     m_backgroundItem = new QGraphicsRectItem(m_svgItem->boundingRect()); // 设置背景项  
  52.     m_backgroundItem->setBrush(Qt::white);  
  53.     m_backgroundItem->setPen(Qt::NoPen);  
  54.     m_backgroundItem->setVisible(drawBackground);  
  55.     m_backgroundItem->setZValue(-1);  
  56.   
  57.     m_outlineItem = new QGraphicsRectItem(m_svgItem->boundingRect());    // 设置边框项  
  58.     QPen outline(Qt::black, 2, Qt::DashLine);  
  59.     outline.setCosmetic(true);  
  60.     m_outlineItem->setPen(outline);  
  61.     m_outlineItem->setBrush(Qt::NoBrush);  
  62.     m_outlineItem->setVisible(drawOutline);  
  63.     m_outlineItem->setZValue(1);  
  64.   
  65.     s->addItem(m_backgroundItem);                   // 将svg内容,边框,背景添加到Scene  
  66.     s->addItem(m_svgItem);  
  67.     s->addItem(m_outlineItem);  
  68.   
  69.     s->setSceneRect(m_outlineItem->boundingRect().adjusted(-10, -10, 10, 10));  
  70. }  
  71.   
  72. void SvgView::setRenderer(RendererType type)       // 选择renderer设置视口  
  73. {  
  74.     m_renderer = type;  
  75.   
  76.     if (m_renderer == OpenGL) {  
  77. #ifndef QT_NO_OPENGL  
  78.         setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));  
  79. #endif  
  80.     } else {  
  81.         setViewport(new QWidget);  
  82.     }  
  83. }  
  84.   
  85. void SvgView::setHighQualityAntialiasing(bool highQualityAntialiasing)  // 高质量反走样 槽  
  86. {  
  87. #ifndef QT_NO_OPENGL  
  88.     setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);  
  89. #else  
  90.     Q_UNUSED(highQualityAntialiasing);  
  91. #endif  
  92. }  
  93.   
  94. void SvgView::setViewBackground(bool enable)        // 设置背景 槽  
  95. {  
  96.     if (!m_backgroundItem)  
  97.           return;  
  98.   
  99.     m_backgroundItem->setVisible(enable);  
  100. }  
  101.   
  102. void SvgView::setViewOutline(bool enable)           // 设置outline 槽  
  103. {  
  104.     if (!m_outlineItem)  
  105.         return;  
  106.   
  107.     m_outlineItem->setVisible(enable);  
  108. }  
  109.   
  110. void SvgView::paintEvent(QPaintEvent *event)        // 选择Image时,将view内容以图片形式绘制出来,通过viewport()  
  111. {  
  112.     if (m_renderer == Image) {  
  113.         if (m_image.size() != viewport()->size()) {  
  114.             m_image = QImage(viewport()->size(), QImage::Format_ARGB32_Premultiplied);  
  115.         }  
  116.   
  117.         QPainter imagePainter(&m_image);  
  118.         QGraphicsView::render(&imagePainter);  
  119.         imagePainter.end();  
  120.   
  121.         QPainter p(viewport());  
  122.         p.drawImage(0, 0, m_image);  
  123.   
  124.     } else {  
  125.         QGraphicsView::paintEvent(event);  
  126.     }  
  127. }  
  128.   
  129. void SvgView::wheelEvent(QWheelEvent *event)  
  130. {  
  131.     qreal factor = qPow(1.2, event->delta() / 240.0);  
  132.     scale(factor, factor);              // 伸缩view  
  133.     event->accept();                    // accept()事件  
  134. }  


[cpp]  view plain copy
  1. class MainWindow : public QMainWindow  
  2. {  
  3.     Q_OBJECT  
  4.   
  5. public:  
  6.     MainWindow();  
  7.   
  8. public slots:  
  9.     void openFile(const QString &path = QString()); // 打开文件槽  
  10.     void setRenderer(QAction *action);              // 设置renderer槽  
  11.   
  12. private:  
  13.     QAction *m_nativeAction;                    //用于菜单项的动作  
  14.     QAction *m_glAction;  
  15.     QAction *m_imageAction;  
  16.     QAction *m_highQualityAntialiasingAction;  
  17.     QAction *m_backgroundAction;  
  18.     QAction *m_outlineAction;  
  19.   
  20.     SvgView *m_view;                            // MainWindow中心的View部件  
  21.   
  22.     QString m_currentPath;                      // open file时的路径  
  23. };  


[cpp]  view plain copy
  1. MainWindow::MainWindow()  
  2.     : QMainWindow()  
  3.     , m_view(new SvgView)  
  4. {  
  5.     QMenu *fileMenu = new QMenu(tr("&File"), this);               // 创建file菜单  
  6.     QAction *openAction = fileMenu->addAction(tr("&Open..."));    // 添加open菜单项  
  7.     openAction->setShortcut(QKeySequence(tr("Ctrl+O")));          // 快捷键  
  8.     QAction *quitAction = fileMenu->addAction(tr("E&xit"));       // 添加Exit菜单项  
  9.     quitAction->setShortcuts(QKeySequence::Quit);                 // 快捷键  
  10.   
  11.     menuBar()->addMenu(fileMenu);                                 // 添加到菜单栏  
  12.   
  13.     QMenu *viewMenu = new QMenu(tr("&View"), this);               // 创建view菜单  
  14.     m_backgroundAction = viewMenu->addAction(tr("&Background"));  // 添加背景菜单项  
  15.     m_backgroundAction->setEnabled(true);                        // 设置不可用  
  16.     m_backgroundAction->setCheckable(true);                       // 设置可打勾选择  
  17.     m_backgroundAction->setChecked(false);                        // 初始化不打勾  
  18.     // 设置信号槽,背景动作激发m_view成员的槽setViewBackground  
  19.     connect(m_backgroundAction, SIGNAL(toggled(bool)), m_view, SLOT(setViewBackground(bool)));  
  20.   
  21.     m_outlineAction = viewMenu->addAction(tr("&Outline"));        // 添加菜单项:外围包围线  
  22.     m_outlineAction->setEnabled(false);                           // 设置不可用  
  23.     m_outlineAction->setCheckable(true);                          // 设置可打勾选择  
  24.     m_outlineAction->setChecked(true);                            // 初始化打勾  
  25.     // 设置信号槽,包围线触发m_view成员的槽setViewOutline  
  26.     connect(m_outlineAction, SIGNAL(toggled(bool)), m_view, SLOT(setViewOutline(bool)));  
  27.   
  28.     menuBar()->addMenu(viewMenu);                                 // 将view菜单添加到菜单栏  
  29.   
  30.     QMenu *rendererMenu = new QMenu(tr("&Renderer"), this);       // 创建Renderer菜单  
  31.     m_nativeAction = rendererMenu->addAction(tr("&Native"));      // 添加Native菜单项  
  32.     m_nativeAction->setCheckable(true);                           // 设置可打勾选择  
  33.     m_nativeAction->setChecked(true);                             // 初始化打勾  
  34. #ifndef QT_NO_OPENGL     // 如果定义了QT_NO_OPENGL就不添加OPNGL相关的菜单项  
  35.     m_glAction = rendererMenu->addAction(tr("&OpenGL"));          // 添加OpenGL菜单项  
  36.     m_glAction->setCheckable(true);                               // 设置可打勾选择  
  37. #endif  
  38.     m_imageAction = rendererMenu->addAction(tr("&Image"));        // 添加Image菜单项  
  39.     m_imageAction->setCheckable(true);                            // 设置可打勾选择  
  40.   
  41. #ifndef QT_NO_OPENGL  
  42.     rendererMenu->addSeparator();                                 // 添加分隔线  
  43.     // 添加高质量反走样菜单项  
  44.     m_highQualityAntialiasingAction = rendererMenu->addAction(tr("&High Quality Antialiasing"));  
  45.     m_highQualityAntialiasingAction->setEnabled(false);  
  46.     m_highQualityAntialiasingAction->setCheckable(true);  
  47.     m_highQualityAntialiasingAction->setChecked(false);  
  48.     // 添加信号槽,触发m_view的setHightQualityAntialasing  
  49.     connect(m_highQualityAntialiasingAction, SIGNAL(toggled(bool)), m_view, SLOT(setHighQualityAntialiasing(bool)));  
  50. #endif  
  51.   
  52.     // 将native,opengl,image菜单项组合在一起(每次只选择其中的一个)  
  53.     QActionGroup *rendererGroup = new QActionGroup(this);  
  54.     rendererGroup->addAction(m_nativeAction);  
  55. #ifndef QT_NO_OPENGL  
  56.     rendererGroup->addAction(m_glAction);  
  57. #endif  
  58.     rendererGroup->addAction(m_imageAction);  
  59.   
  60.     menuBar()->addMenu(rendererMenu);                           // renderer菜单添加到菜单栏  
  61.   
  62.     connect(openAction, SIGNAL(triggered()), this, SLOT(openFile())); // openAction连接槽openFile  
  63.     connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));     // quitAction连接到quit槽  
  64.     connect(rendererGroup, SIGNAL(triggered(QAction*)),  
  65.             this, SLOT(setRenderer(QAction*)));                       // rendererGroup连接到setRender槽  
  66.   
  67.     setCentralWidget(m_view);           // 将svg view窗体部件放置MainWindow中心  
  68.     setWindowTitle(tr("SVG Viewer"));   // 标题  
  69. }  
  70.   
  71. void MainWindow::openFile(const QString &path)  
  72. {  
  73.     QString fileName;  
  74.     if (path.isNull())                 // FileDialog获得路径  
  75.         fileName = QFileDialog::getOpenFileName(this, tr("Open SVG File"),  
  76.                 m_currentPath, "SVG files (*.svg *.svgz *.svg.gz)");  
  77.     else  
  78.         fileName = path;  
  79.   
  80.     if (!fileName.isEmpty()) {         // 处理获得的文件路径  
  81.         QFile file(fileName);  
  82.         if (!file.exists()) {          // 文件不存在:弹出MessageBox提示  
  83.             QMessageBox::critical(this, tr("Open SVG File"),  
  84.                            QString("Could not open file '%1'.").arg(fileName));  
  85.   
  86.             m_outlineAction->setEnabled(false);                    // outline,background菜单项不可用  
  87.             m_backgroundAction->setEnabled(false);  
  88.             return;  
  89.         }  
  90.   
  91.         m_view->openFile(file);                  // 将文件在svg view上打开  
  92.   
  93.         if (!fileName.startsWith(":/")) {        // 更改窗体标题  
  94.             m_currentPath = fileName;  
  95.             setWindowTitle(tr("%1 - SVGViewer").arg(m_currentPath));  
  96.         }  
  97.   
  98.         m_outlineAction->setEnabled(true);       // 是菜单项outline,background可用  
  99.         m_backgroundAction->setEnabled(true);  
  100.   
  101.         resize(m_view->sizeHint() + QSize(80, 80 + menuBar()->height()));  
  102.     }  
  103. }  
  104.   
  105. void MainWindow::setRenderer(QAction *action)    //setRenderer槽  
  106. {  
  107. #ifndef QT_NO_OPENGL  
  108.     m_highQualityAntialiasingAction->setEnabled(false);  
  109. #endif  
  110.   
  111.     // 将当前renderer设置为菜单中选择的  
  112.     if (action == m_nativeAction)  
  113.         m_view->setRenderer(SvgView::Native);  
  114. #ifndef QT_NO_OPENGL  
  115.     else if (action == m_glAction) {  
  116.         m_highQualityAntialiasingAction->setEnabled(true);  
  117.         m_view->setRenderer(SvgView::OpenGL);  
  118.     }  
  119. #endif  
  120.     else if (action == m_imageAction) {  
  121.         m_view->setRenderer(SvgView::Image);  
  122.     }  
  123. }  

你可能感兴趣的:(Qt)