目的
本文简述如何在qml中调用c++代码。通过qml调用c++主要有两种方法:使用qmlRegisterType()与setContextProperty()。下面依次介绍
qmlRegisterType
新建Qt工程后,编辑mainwindow.h如下。程序运行后,会调用 CallMe.hello()函数输出相关信息。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
class CallMe : public QObject {
Q_OBJECT
public:
explicit CallMe (QObject* parent = 0) : QObject(parent) {}
Q_INVOKABLE void hello() {
qDebug() << "Hello,World";
}
};
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
编辑mainwindow.cpp如下:
#include "mainwindow.h"
#include <QHBoxLayout>
#include <QQmlEngine>
#include <QQuickWidget>
#include <QQmlContext>
#include <QQuickItem>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) {
QQmlEngine *engine = new QQmlEngine(this);
QQuickWidget *view = new QQuickWidget(engine, this);
setCentralWidget(view);
view->setSource(QUrl("qrc:/main.qml"));
view->setResizeMode(QQuickWidget::SizeRootObjectToView);
}
MainWindow::~MainWindow() {
}
编辑main.cpp如下,在main函数的开始将CallMe类注册到QML中,以便在QML中可以创建此类的对象。
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include "qqml.h"
int main(int argc, char *argv[]) {
qmlRegisterType<CallMe>("com.test", 1, 0, "CallMe");
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
编辑main.qml内容如下,main.qml的第三行导入了com.test命名空间,在第8行创建了CallMe的对象,id为callMe。这样在button按下后就可以调用callMe.hello()函数。
import QtQuick 2.0
import QtQuick.Controls 2.12
import com.test 1.0
Rectangle {
color: "red"
CallMe {
id: callMe
}
Button {
text: qsTr("Hello, World")
anchors.centerIn: parent
onClicked: callMe.hello()
}
}
如果顺利的话,运行Demo后点击按钮就可以看到打印输出,表明可以通过QML调用cpp的代码。
setContextProperty
第二种方法个人感觉要简单点儿,mainwindow.h代码如下,最终会调用MainWindow.hello() 方法,在QT中被标注为一个slot。
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
class MainWindow : public QMainWindow {
Q_OBJECT
public slots:
void hello();
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
mainwindow.cpp代码如下,在构造函数的最后调用setContextProperty()将MainWindow的对象注册为QML中的对象。
#include "mainwindow.h"
#include <QHBoxLayout>
#include <QQmlEngine>
#include <QQuickWidget>
#include <QQmlContext>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) {
QQmlEngine *engine = new QQmlEngine(this);
QQuickWidget *view = new QQuickWidget(engine, this);
setCentralWidget(view);
view->setSource(QUrl("qrc:/main.qml"));
view->setResizeMode(QQuickWidget::SizeRootObjectToView);
view->rootContext()->setContextProperty("mainWindow", this);
}
MainWindow::~MainWindow() {
}
void MainWindow::hello() {
qDebug() << "Hello, World";
}
main.cpp代码如下:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
最后看看main.qml调用MainWindow.hello()的过程:
import QtQuick 2.0
import QtQuick.Controls 2.12
Rectangle {
color: "red"
Button {
text: qsTr("Hello, World")
anchors.centerIn: parent
onClicked: mainWindow.hello()
}
}
总结
- 上述两种方法都可以通过QML调用c++代码。
- 方法一调用的对象是在QML中创建的(callMe),第二种方法在c++中(mainWindow)。
- c++中声明的slots方法可以直接被QML调用。
引用
https://stackoverflow.com/questions/9500280/access-c-function-from-qml
https://stackoverflow.com/questions/26399368/calling-c-function-from-qml-code