QMLC++ 混合编程就是使用 QML 高效便捷地构建 UI,而 C++ 则用来实现业务逻辑和复杂算法。

1 QML访问C++

QML访问C++有两个方法:

  1. Qt元对象系统中注册C++类,在QML中实例化、访问。

  2. 在C++中实例化,并设置为QML上下文属性,在QML中直接使用。

2 C++访问QML

C++ 访问 QML 的前提是获取到实例化 Item 对象的指针。

QML创建的实例化的组件有一个对象树,可以一层一层获取含有哪些对象的指针,但是,好像有些对象是无法获取到指针的,导致无法使用C++访问QML。

无论使用 QQmlComponent,还是使用 QQmlApplicationEngine 实例化创建 QML 界面,获取Item对象,有些对象的地址可以获取,有些不能获取。

2.1 验证获取QML实例化对象指针

下面是 qml 文件内容,Window 窗口对象是顶层。

注意:rect 对象下面有 rect1rect2

alt text

2.1.1 跟窗口下获取子对象

通过以下代码,可以获取到 chartViewrect

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();
}

alt text

2.1.2 chartView获取子对象

通过以下代码,并不能获取到可以获取到 axisXaxisXchartView

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();
}

alt text

2.1.2 rect获取子对象

通过以下代码,并不能获取到可以获取到 rect1rect2

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();
}

alt text

可以主要参考: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
}