学习QT之显示SVG格式图片

SVG的英文全称是Scalable Vector Graphics,即可缩放的矢量图形。它是有万维网联盟在2000年8月制定的一种新的二维矢量图形格式,也是规范中的网格矢量图形标准,是一个开发的图形标准。

SVG格式的特点如下:

  • 基于XML
  • 采用文本来描述对象
  • 具有交互性和动态性
  • 完全支持DOM

SVG相对于GIF、JPEG格式的优势是,SVG是一种矢量图形格式,比GIF、JPEG等栅格格式具有众多优势,如文件小,对于网络而言,下载速度快;可任意缩放而不会破坏图像的清晰度和细节;图像中的文字独立于图像,文字保留可编辑和可搜寻的状态,也没有字体限制,用户系统即使没有安装某一种字体,也可看到与制作时完全相同的画面等。正是基于其格式的各种优点及开放性,SVG得到了众多组织和知名厂商的支持与认可,因此能够迅速地开发和推广应用。


概念解析

XML

Qt的XML模块支持两种XML解析方法:DOM和SAX。其中,DOM方法将XML文件表示为一棵树,以便随机访问其中的结点,但消耗内存相对多一些。而SAX是一种事件驱动的XML API,其速度快,但不便于随机访问任意结点。因此,通常根据实际应用选择合适的解析方法。这里只介绍DOM的使用方法。

文档对象模型(Document Object Model,DOM)是W3C开发的独立于平台和语言的接口,它可以使程序和脚本动态地存取和更新XML文档的内容、结构和风格。

DOM在内存中将XML文件表示为一棵树,用户通过API可以随意的访问数的任意结点内容。在Qt中,XML文档自身用QDomDocument表示,所有的结点类都从QDomNode继承。

SVG文件是利用XML表示的矢量图形文件,每种图形都用XML标签表示。例如,在SVG中画折线的标签如下:

<polyline fill="none" stroke="#888888" stroke-width="2" points="100,200,100,100"/>

其中

  • polyline:表示绘制折线
  • fill:表示填充
  • stroke:表示画笔颜色
  • stroke-width:表示画笔宽度
  • points:表示折线的点

Qt为SVG格式图片的显示与生成提供了专门的QtSvg模块,此模块中包含了与SVG图片相关的所有类,主要有QSvgWidgetQSvgRenderQGraphicsSvgItem

下面通过一个实例来介绍它的使用

一、运行结果

在这里插入图片描述
在这里插入图片描述

二、详细代码

在完成此功能的程序中使用与SVG相关的类,必须在程序中包含SVG相关的头文件:#include <QtSvg>

由于Qt默认生成的Makefile中只加入了QtGui、QtCore模块的库,所以必须在工程文件.pro中加入一行代码

QT += svg

svgwidget.h

#ifndef SVGWIDGET_H
#define SVGWIDGET_H

#include <QtSvg/QSvgWidget>
#include <QtSvg/QSvgRenderer>
#include <QMouseEvent>

class SvgWidget : public QSvgWidget
{
    Q_OBJECT
public:
    SvgWidget(QWidget *parent=0);
    void wheelEvent(QWheelEvent *);
    //响应鼠标的滚轮事件,使SVG图片能够通过鼠标滚轮的滚动进行缩放

private:
    QSvgRenderer *render;  //用于图片显示尺寸的确定
};

#endif // SVGWIDGET_H

svgwidget.cpp

#include "svgwidget.h"

SvgWidget::SvgWidget(QWidget *parent)
    : QSvgWidget(parent)
{
    render = renderer();
}

void SvgWidget::wheelEvent(QWheelEvent *e)
{
    const double diff = 0.1;  //diff值表示每次滚轮滚动一定的值,图片大小改变的比例
    QSize size = render->defaultSize();  //用于获取图片显示区的尺寸
    int width = size.width();
    int height = size.height();
    if(e->delta() > 0)  //利用QWheelEvent的delta()函数获得滚轮滚动的距离值,通过此值来判断滚轮滚动的方向
    {
        //若delta()值大于零,则表示滚轮向前(远离用户的方向)滚动
        width = int(this->width() + this->width()*diff);
        height = int(this->height() + this->height()*diff);
    }
    else
    {
        //若delta()值小于零,则表示滚轮向后(靠近用户的方向)滚动
        width = int(this->width() - this->width()*diff);
        height = int(this->height() - this->height()*diff);
    }
    resize(width,height);
}

:鼠标滚动时间,滚轮每滚动1°相当于移动了8°,而常见的滚轮鼠标拨动一下滚动的角度为15°,因此滚轮拨动一下相当于移动了120(15*8)° 。

svgwindow.h

#ifndef SVGWINDOW_H
#define SVGWINDOW_H

#include <QScrollArea>
#include "svgwidget.h"
#include <QMouseEvent>
#include <QScrollBar>


class SvgWindow : public QScrollArea
{
    Q_OBJECT
public:
    SvgWindow(QWidget *parent = 0);
    void setFile(QString);
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);

private:
    SvgWidget *svgWidget;
    QPoint mousePressPos;
    QPoint scrollBarValuesOnMousePress;
};

#endif // SVGWINDOW_H

svgwindow.cpp

#include "svgwindow.h"

SvgWindow::SvgWindow(QWidget *parent)
    : QScrollArea(parent)
{
    svgWidget = new SvgWidget;
    setWidget(svgWidget);
}

void SvgWindow::setFile(QString fileName)
{
    svgWidget->load(fileName);
    QSvgRenderer *render = svgWidget->renderer();
    svgWidget->resize(render->defaultSize());
}

void SvgWindow::mousePressEvent(QMouseEvent *event)
{
    mousePressPos = event->pos();
    scrollBarValuesOnMousePress.rx()=horizontalScrollBar()->value();
    scrollBarValuesOnMousePress.ry()=verticalScrollBar()->value();
}

void SvgWindow::mouseMoveEvent(QMouseEvent *event)
{
    //对水平滚动条的新位置进行设置
    horizontalScrollBar()->setValue(scrollBarValuesOnMousePress.x() - event->pos().x() + mousePressPos.x());
    //对垂直滚动条的新位置进行设置
    verticalScrollBar()->setValue(scrollBarValuesOnMousePress.y() - event->pos().y() + mousePressPos.y());
    horizontalScrollBar()->update();
    event->accept();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "svgwindow.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void createMenu();

public slots:
    void slotOpenFile();

private:
    SvgWindow *svgWindow;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include <QMenuBar>
#include <QMenu>
#include <QFileDialog>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle(tr("SVG Viewer"));
    createMenu();
    svgWindow = new SvgWindow;
    setCentralWidget(svgWindow);
    setMinimumSize(600,400);
}

MainWindow::~MainWindow()
{

}

void MainWindow::createMenu()
{
    QMenu *fileMenu = menuBar()->addMenu(tr("文件"));
    QAction *openAct = new QAction(tr("打开"),this);
    connect(openAct,SIGNAL(triggered(bool)),this,SLOT(slotOpenFile()));
    fileMenu->addAction(openAct);
}

void MainWindow::slotOpenFile()
{
    QString name = QFileDialog::getOpenFileName(this,"打开","/","svg files(*.svg)");
    svgWindow->setFile(name);
}
  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贝勒里恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值