在这篇文章中,我讲述如果使用QML来调用C++来扩展我们的应用。我们知道,在许多的场景中,QML虽然很强大,在UI方面是非常突出的,但是,有的时候,我们可能会想到应用我们的C++代码。这有一下方面的原因:
1)我们已经有成熟的C++引擎设计或协议等。比如我们已经用C++设计好了我们的Fetion协议代码。我们没要再用另外一个低性能的语言来重新写一边
2)有些功能我们没有办法使用Javascript来完成,必须使用系统或专用的一些功能包来完成。这时我们可以使用C++语言来完成我们需要的功能
3)有些代码对计算的要求非常高,需要使用大量的CPU时间,这时,我们可以考虑使用C++来完成这部分的工作
事实上,在Ubuntu OS上,我们可以可以使用QML/Javascript来创建非常炫的UI,同时我们也可以使用C++来完成我们特有的一些功能(比如需要大量计算)。两者之间的结合是非常自然的和密切的。你可以想像C++是可以用来拓展QML的功能的。
在这里,我们来创建一个应用读取Linux的一些环境变量。通过这个练习,我们可以掌握怎么在QML文件中调用C++的代码。
#ifndef READ_ENV_H #define READ_ENV_H #include <QObject> class ReadEnv : public QObject { Q_OBJECT public: explicit ReadEnv(QObject *parent = 0); Q_INVOKABLE QString getenv(const QString envVarName) const; private: }; #endif // READ_ENV_H
#include "readenv.h" #include <QDebug> ReadEnv::ReadEnv(QObject *parent) : QObject(parent) { } QString ReadEnv::getenv(const QString envVarName) const { QByteArray result = qgetenv(envVarName.toStdString().c_str()); QString output = QString::fromLocal8Bit(result); qDebug() << envVarName << " value is: " << output; return output; }
#include <QtQml> #include <QtQml/QQmlContext> #include "backend.h" #include "mytype.h" #include "readenv.h" void BackendPlugin::registerTypes(const char *uri) { Q_ASSERT(uri == QLatin1String("ReadEnv")); qmlRegisterType<MyType>(uri, 1, 0, "MyType"); qmlRegisterType<ReadEnv>(uri, 1, 0, "ReadEnv"); } void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) { QQmlExtensionPlugin::initializeEngine(engine, uri); }
qmlRegisterType<ReadEnv>(uri, 1, 0, "ReadEnv");
set(
modules/ReadEnv/mytype.cpp
modules/ReadEnv/readenv.cpp
)
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: 10
Label {
text: "Value: "
fontSize: "large"
}
TextArea {
id:value
readOnly: true
contentWidth: units.gu(40)
contentHeight: units.gu(80)
}
}
import QtQuick 2.0
import Ubuntu.Components 0.1
import ReadEnv 1.0
import "ui"
MainView {
// objectName for functional testing purposes (autopilot-qt5)
objectName: "mainView"
// Note! applicationName needs to match the "name" field of the click manifest
applicationName: "com.ubuntu.developer.liu-xiao-guo.ReadEnv"
anchorToKeyboard: true
/*
This property enables the application to change orientation
when the device is rotated. The default is false.
*/
//automaticOrientation: true
width: units.gu(100)
height: units.gu(75)
ReadEnv {
id: readEnv
}
Column {
// anchors.fill: parent
// anchors.verticalCenter: parent.verticalCenter
// anchors.horizontalCenter: parent.horizontalCenter
anchors.centerIn: parent
spacing: 20
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: 10
Label {
text: "Variable:"
fontSize: "large"
}
TextField {
id:input
text:"PWD"
focus: true
placeholderText: "Please input a env variable"
Keys.onPressed: {
if (event.key === Qt.Key_Return) {
print("Enter is pressed!")
value.text = readEnv.getenv(input.text)
}
}
}
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: 10
Label {
text: "Value: "
fontSize: "large"
}
TextArea {
id:value
readOnly: true
contentWidth: units.gu(40)
contentHeight: units.gu(80)
}
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: "Get"
onClicked: {
print("Button is clicked!")
value.text = readEnv.getenv(input.text)
}
}
}
}
import ReadEnv 1.0
Q_ASSERT(uri == QLatin1String("ReadEnv"));
ReadEnv {
id: readEnv
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: "Get"
onClicked: {
print("Button is clicked!")
value.text = readEnv.getenv(input.text)
}
}