在我先前的文章"在QML应用中使用Canvas来画图"中,我展示如何利用QML中的Canvas来画我们的曲线.今天在我们的文章中,我们来展示如何利用SVG在我们的例程中画我们所需要的曲线.
我们可以直接使用一个已经存在的SVG画画库simple-svg.它的源码位于"https://code.google.com/archive/p/simple-svg/downloads".对于一下开发者来说可能需要VPN才可以下载哦.
我们可以利用我们的SDK中提供的一个标准的"QML App with C++ plugin (qmake)"来创建一个简单的模版.同时,我们修改我们的plugin的代码如下:
mytype.h
#ifndef MYTYPE_H
#define MYTYPE_H
#include <QObject>
class MyType : public QObject
{
Q_OBJECT
Q_PROPERTY( QString helloWorld READ helloWorld WRITE setHelloWorld NOTIFY helloWorldChanged )
public:
explicit MyType(QObject *parent = 0);
~MyType();
Q_INVOKABLE void draw(const int &width, const int &height, const QString &array);
Q_SIGNALS:
void helloWorldChanged();
protected:
QString helloWorld() { return m_message; }
void setHelloWorld(QString msg) { m_message = msg; Q_EMIT helloWorldChanged(); }
QString m_message;
};
#endif // MYTYPE_H
mytype.cpp
#include "mytype.h"
#include "simple_svg.h"
using namespace svg;
MyType::MyType(QObject *parent) :
QObject(parent),
m_message("")
{
}
MyType::~MyType() {
}
void MyType::draw(const int &width, const int &height, const QString &array)
{
// Create the SVG doc
Dimensions dimensions(width, height);
Document doc("../svggraph/svggraph/graph.svg", Layout(dimensions, Layout::BottomLeft));
// Parse our string into an array
std::istringstream buf(array.toStdString());
std::istream_iterator<std::string> beg(buf), end;
std::vector<std::string> tokens(beg, end);
// Create a line
Polyline polyline_a(Stroke(1.5, Color::Cyan));
// Iterate over our array to define line start/end points
for( int a = 0; a < tokens.size(); a = a + 1 )
{
if (tokens.size() < 2) {
polyline_a << Point(width/(tokens.size())*(a), atoi(tokens[a].c_str())) << Point(width/(tokens.size())*(a+1), atoi(tokens[a].c_str()));
} else {
polyline_a << Point(width/(tokens.size()-1)*(a), atoi(tokens[a].c_str()));
}
}
doc << polyline_a;
// Save the doc
doc.save();
}
svggraph/backend/Svggraph
在我们的Main.qml中,我们可以利用我们刚刚创建的plugin来画我们的UI.和先前不同的是,这里,我们使用一个叫做Image的而不是一个Canvas.
Main.qml
import QtQuick 2.4
import Ubuntu.Components 1.3
import Svggraph 1.0
/*!
\brief MainView with a Label and Button elements.
*/
MainView {
// objectName for functional testing purposes (autopilot-qt5)
objectName: "mainView"
// Note! applicationName needs to match the "name" field of the click manifest
applicationName: "svggraph.liu-xiao-guo"
width: units.gu(60)
height: units.gu(85)
MyType {
id: myType
}
Page {
id: page
header: PageHeader {
id: pageHeader
title: i18n.tr("svggraph")
StyleHints {
foregroundColor: UbuntuColors.orange
backgroundColor: UbuntuColors.porcelain
dividerColor: UbuntuColors.slate
}
}
Rectangle {
anchors {
top:page.header.bottom
left: page.header.left
right: page.header.right
}
height: parent.height - page.header.height
TextField{
id:txt
width:parent.width - units.gu(4)
anchors.top:parent.top
anchors.horizontalCenter:parent.horizontalCenter
anchors.margins:units.gu(2)
text: "0 10 50 80 60 90"
}
Row {
anchors.top:txt.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: units.gu(2)
spacing: units.gu(2)
Button {
id:drawButton
anchors.margins:units.gu(2)
text:i18n.tr("Draw")
enabled:(txt.length)
color: UbuntuColors.orange
onClicked: {
myType.draw(page.width, page.height, txt.text)
img.source = ""
img.source = Qt.resolvedUrl("graph.svg")
}
}
Button {
id:clearButton
anchors.margins:units.gu(2)
text:i18n.tr("Clear")
onClicked: {
myType.draw(page.width, page.height, "")
img.source = ""
img.source = Qt.resolvedUrl("graph.svg")
}
}
}
Image {
id:img
anchors.fill:parent
anchors.margins:units.gu(2)
cache:false
source: Qt.resolvedUrl("graph.svg")
}
}
}
}
在这里,我们通过按钮"Draw"把我们所需要的数据传入到plugin中,并生产graph.svg文件,并在UI的Image中得以显示:
整个项目的源码在:
https://github.com/liu-xiao-guo/svggraph