十九、QML——C++交互
QML
与 C++
混合编程就是使用 QML
高效便捷地构建 UI
,而 C++
则用来实现业务逻辑和复杂算法。
1 QML访问C++
QML访问C++有两个方法:
-
Qt元对象系统中注册C++类,在QML中实例化、访问。
-
在C++中实例化,并设置为QML上下文属性,在QML中直接使用。
2 C++访问QML
C++
访问 QML
的前提是获取到实例化 Item
对象的指针。
无论使用 QQmlComponent
,还是使用 QQmlApplicationEngine
实例化创建 QML
界面,获取Item对象,有些对象的地址可以获取,有些不能获取。
2.1 验证获取QML实例化对象指针
下面是 qml
文件内容,Window
窗口对象是顶层。
注意:rect
对象下面有 rect1
和 rect2
。
2.1.1 跟窗口下获取子对象
通过以下代码,可以获取到 chartView
和 rect
:
int main(int argc, char *argv[])
{
/* QtCharts 使用 Qt Graphics View Framework 进行绘制,因此 QApplication一定要被使用,而不是 QGuiApplication */
QApplication app(argc, argv);
QQmlApplicationEngine engine;
/* 如果 engine 在加载 QML 文件时遇到任何问题,例如 QML 文件中有语法错误,或者无法加载所需的组件,那么会发射 objectCreationFailed 信号。 */
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
&app, []() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
QQmlComponent component(&engine, QUrl(QStringLiteral("../../MyLineSeries.qml")));
QObject *object = component.create();
QObject *rect = object->findChild<QObject *>("rect");
const QList<QObject*> children = object->children();
for (QObject *child : children) {
qDebug() << "顶层root下 Child:" << child->objectName();
}
return app.exec();
}
2.1.2 chartView获取子对象
通过以下代码,并不能获取到可以获取到 axisX
和 axisX
和 chartView
:
int main(int argc, char *argv[])
{
/* QtCharts 使用 Qt Graphics View Framework 进行绘制,因此 QApplication一定要被使用,而不是 QGuiApplication */
QApplication app(argc, argv);
QQmlApplicationEngine engine;
/* 如果 engine 在加载 QML 文件时遇到任何问题,例如 QML 文件中有语法错误,或者无法加载所需的组件,那么会发射 objectCreationFailed 信号。 */
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
&app, []() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
QQmlComponent component(&engine, QUrl(QStringLiteral("../../MyLineSeries.qml")));
QObject *object = component.create(); /* 根对象 */
QObject *chartView = object->findChild<QObject *>("chartView");
const QList<QObject*> children = chartView->children();
for (QObject *child : children) {
qDebug() << "chartview下 Child:" << child->objectName();
}
return app.exec();
}
2.1.2 rect获取子对象
通过以下代码,并不能获取到可以获取到 rect1
和 rect2
:
int main(int argc, char *argv[])
{
/* QtCharts 使用 Qt Graphics View Framework 进行绘制,因此 QApplication一定要被使用,而不是 QGuiApplication */
QApplication app(argc, argv);
QQmlApplicationEngine engine;
/* 如果 engine 在加载 QML 文件时遇到任何问题,例如 QML 文件中有语法错误,或者无法加载所需的组件,那么会发射 objectCreationFailed 信号。 */
QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed,
&app, []() { QCoreApplication::exit(-1); },
Qt::QueuedConnection);
QQmlComponent component(&engine, QUrl(QStringLiteral("../../MyLineSeries.qml")));
QObject *object = component.create(); /* 根对象 */
QObject *rect = object->findChild<QObject *>("rect");
const QList<QObject*> children = rect->children();
for (QObject *child : children) {
qDebug() << "rect下 Child:" << child->objectName();
}
return app.exec();
}
可以主要参考:https://www.nxrte.com/jishu/11158.html
参考:https://www.cnblogs.com/jzcn/p/17774676.html
https://blog.csdn.net/zwcslj/article/details/140618579
https://blog.csdn.net/sjp11/article/details/131617850
https://doc.qt.io/qt-6/qtcharts-qmlaxes-example.html
https://stuff.mit.edu/afs/athena/software/texmaker_v5.0.2/qt57/doc/qtcharts/qtcharts-qmlaxes-example.html
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "autogen/environment.h"
#include <QQmlContext>
#include <QQmlProperty>
#include <QDebug>
#include <QTimer>
class Backend : public QObject
{
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
public:
QString text() const { return mText; }
void setText(const QString &text)
{
if (text == mText)
return;
mText = text;
emit textChanged(mText);
}
signals:
void textChanged(const QString &text);
private:
QString mText;
};
int main(int argc, char *argv[])
{
Backend backend;
QStringList dataList = {
"COM1",
"COM2",
"COM3",
"COM4"
};
set_qt_environment();
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
backend.setText(QString("50"));
engine.rootContext()->setContextProperty("backend", &backend);
engine.rootContext()->setContextProperty("model1", QVariant::fromValue(dataList));
const QUrl url(mainQmlFile);
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
engine.addImportPath(":/");
engine.load(url);
if (engine.rootObjects().isEmpty())
return -1;
QObject::connect(&backend, &Backend::textChanged,
[](const QString & text) { qDebug() << text; });
return app.exec();
}
#include "main.moc"
TextInput {
text: backend.text
anchors.fill: parent
font.pixelSize: 12
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
onTextChanged: backend.text = text
}