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图片相关的所有类,主要有QSvgWidget
、QSvgRender
、QGraphicsSvgItem
。
下面通过一个实例来介绍它的使用:
一、运行结果
二、详细代码
在完成此功能的程序中使用与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);
}