SVG 的英文全称是 Scalable Vector Graphics,即可缩放的矢量图形。它是由万维网络联盟 ( World Wide Web Consortium, W3C ) 在 2000 年 8 月制定的一种新的二维矢量图形格式,也是规范中的网格矢量图形标准,是一个开放的图形标准。
SVG 格式的特点如下:
(1)基于 XML。
(2)采用文本来描述对象。
(3)具有交互性和动态性。
(4)完全支持 DOM。
SVG 相对于 GIF、JPEG 格式的优势是,SVG 是一种矢量图形格式,比 GIF、JPEG 等栅格格式具有众多优势,如文件小,对于网络而言,下载速度快;可任意缩放而不会破坏图像的清晰度和细节;图像中的文字独立于图像,文字保留可编辑和可搜寻的状态,也没有字体限制,用户系统即使没有安装某一种字体,也可以看到与制作时完全相同的画面等。正是基于其格式的各种优点及开放性,SVG 得到了众多组织和知名厂商的支持与认可,因此能够迅速地开发和推广应用。
Qt 为 SVG 格式图片的显示与生成提供了专门的 QtSvg 模块,此模块中包含了与 SVG 图片相关的所有类,主要有 QSvgWidget、QSvgRender 和 QGraphicsSvgItem。
通过利用 QSvgWidget 类和 QSvgRender 类实现一个 SVG 图片浏览器,显示以 " .svg " 结尾的文件以介绍 SVG 格式图片显示的方法。
绘图工具框架:
(1)SvgWidget 类继承自 QSvgWidget 类,主要显示 SVG 图片。
SvgWidget 构造函数获得本窗体的 QSvgRenderer 对象;具体代码如下:
SvgWidget::SvgWidget(QWidget *parent):QSvgWidget(parent)
{
render = renderer();
}
(2)鼠标滚轮的响应事件,使 SVG 图片能够通过鼠标滚轮的滚动进行缩放;具体代码如下:
void SvgWidget::wheelEvent(QWheelEvent *e)
{
const double diff = 0.1; //(a)
QSize size = render->defaultSize(); //(b)
int width = size.width();
int height = size.height();
if(e->delta() > 0) //(c)
{
//对图片的长、宽值进行处理,放大一定的比例
width = int(this->width() + this->width()*diff);
height = int(this->height() + this->height()*diff);
}
else
{
//对图片的长、宽值进行处理,缩小一定的比例
width = int(this->width() - this->width()*diff);
height = int(this->height() - this->height()*diff);
}
resize(width, height); //利用新的长、宽值对图片进行resize()操作
}
(a)diff 的值表示每次滚轮滚动一定的值,图片大小改变的比例。
(b)该行及下面两行代码用于获取图片显示区的尺寸,以便进行下一步的缩放操作。
(c)利用 QWheelEvent 的 delta() 函数获得滚轮滚动的距离值,通过此值来判断滚轮滚动的方向。若 delta() 值大于零,则表示滚轮向前(远离用户的方向)滚动;若小于零,则表示向后(靠近用户的方向)滚动。
鼠标滚动事件,滚轮没滚动 1° 相当于移动 8° ,而常见的滚轮鼠标拨动一下滚动的角度为 15°,因此滚轮拨动一下相当于移动了 120(=15*8)°。
(3)SvgWindow 类继承自 QScrollArea 类,是一个带滚动条的显示区域。在 SvgWindow 类实现中包含 SvgWidget 类的头文件。SvgWindow 类使图片在放大到超过主窗口大小时,能够通过拖拽滚动条的方式进行查看。
SvgWindow 类的构造函数,构造 SvgWidget 对象,并调用 QScrollArea 类的 setWidget() 函数设置滚动区域的窗体,使 svgWidget 成为 SvgWindow 的子窗口。
具体代码如下:
SvgWindow::SvgWindow(QWidget *parent):QScrollArea(parent)
{
svgWidget = new SvgWidget();
setWidget(svgWidget);
}
(4)当主窗口中对文件进行了选择或修改时,将调用 setFile() 函数设置新的文件,具体代码如下:
void SvgWindow::setFile(QString fileName)
{
svgWidget->load(fileName); //(a)
QSvgRenderer *render = svgWidget->renderer();
svgWidget->resize(render->defaultSize()); //(b)
}
(a)将新的 SVG 文件加载到 svgWidget 中进行显示。
(b)使 svgWidget 窗体按 SVG 图片的默认尺寸进行显示。
(5)当鼠标键被按下时,对 mousePressPos 和 scrollBarValuesOnMousePress 进行初始化,QScrollArea 类的 herizontalScrollBar() 和 verticalScrollBar() 函数可以分别获得 svgWindow 的水平滚动条和垂直滚动条。具体代码如下:
void SvgWindow::mousePressEvent(QMouseEvent *event)
{
mousePressPos = event->pos();
scrollBarValuesOnMousePress.rx() = horizontalScrollBar()->value();
scrollBarValuesOnMousePress.ry() = verticalScrollBar()->value();
event->accept();
}
(6)当鼠标键被按下并拖拽鼠标时触发 mouseMoveEvent() 函数,通过滚动条的位置设置实现图片拖拽的效果,具体代码如下:
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();
verticalScrollBar()->update();
event->accept();
}
(7)主窗口 MainWindow 继承自 QMainWindow 类,包含一个菜单栏,其中有一个“文件”菜单条,包含一个“打开”菜单项。
在 MainWindow 构造函数中,创建一个 SvgWindow 对象作为主窗口的中央窗体。具体代码如下:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle(QObject::tr("SVG Viewer"));
createMenu();
svgWindow = new SvgWindow();
setCentralWidget(svgWindow);
}
(8)创建菜单栏,具体代码如下:
void MainWindow::createMenu()
{
QMenu *fileMenu = menuBar()->addMenu(QObject::tr("文件"));
QAction *openAct = new QAction(QObject::tr("打开"), this);
connect(openAct, SIGNAL(triggered()), this, SLOT(slotOpenFile()));
fileMenu->addAction(openAct);
}
(9)通过标准文件对话框选择 SVG 文件,并调用 SvgWindow 的 setFile() 函数将选择的文件名传递给 svgWindow 进行显示,具体代码如下:
void MainWindow::slotOpenFile()
{
QString name = QFileDialog::getOpenFileName(this, "打开", "/", "svg files(*.svg)");
svgWindow->setFile(name);
}
补充、Qt 5 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:表示折线的点。