Qt提供在widgets和其他paint device上渲染和展示SVG的类,本例就允许用户载入SVG文件并在QGraphicsView上用QGraphicsSvgItem显示它。并且例子还可以选择渲染者,QGraphicsView可以用QWidget或QGLWidget作为视口。也可以使用第三方渲染模型通过QImage。
程序运行如图:renderer可以选择:Native,OpenGL,Image
程序的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
- 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);
- }
- }
FROM: http://blog.csdn.net/xuguangsoft/article/details/8578070