QML与C++ 交互详解

QML与C++ 交互详解

这里我们分别介绍下QML 如何访问C++ 类,以及C++ 如何与QML 交互。

(一) QML如何访问C++ 类:

  • 话不多说我们先看代码:
#include "fpsitem.h"

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    qmlRegisterType<FpsItem>("an.item", 1, 0, "FpsItem");

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

#ifndef FPSITEM_H
#define FPSITEM_H

#include <QQuickItem>

class FpsItem : public QQuickItem
{
    Q_OBJECT

    Q_PROPERTY(int fps READ fps NOTIFY fpsChanged)

public:
    FpsItem(QQuickItem *parent = nullptr);

    int fps() const;

signals:
    void fpsChanged();

private:
    int m_fps = 0;
    int m_frameCount = 0;
};

#endif // FPSITEM_H

#include "fpsitem.h"

#include <QQuickWindow>
#include <QTimer>

FpsItem::FpsItem(QQuickItem *parent)
    : QQuickItem(parent)
{
    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, [this]{ m_fps = m_frameCount; m_frameCount = 0; emit fpsChanged(); });
    connect(this, &QQuickItem::windowChanged, this, [this]{
        if (window())
            connect(window(), &QQuickWindow::afterRendering, this
                    , [this]{ m_frameCount++; }, Qt::DirectConnection);
    });
    timer->start(1000);
}

int FpsItem::fps() const
{
    return m_fps;
}

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Shapes 1.15

import an.item 1.0

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("FpsItem Test")

    FpsItem {
        id: fpsItem
    }

    Item {
        id: back
        anchors.fill: parent
        layer.enabled: true
        layer.smooth: true
        layer.samples: 8

        property bool running: false

        MouseArea {
            anchors.fill: parent
            onClicked: parent.running = !parent.running;
        }

        PathAnimation {
            target: ball
            running: back.running
            duration: 4000
            loops: -1
            path: Path {
                startX: -ball.width * 0.5
                startY: back.height - ball.height * 0.5
                PathCurve { x: back.width * 0.8 - ball.width * 0.5; y: back.height * 0.8 - ball.height * 0.5 }
                PathCurve { x: back.width * 0.2 - ball.width * 0.5; y: back.height * 0.2 - ball.height * 0.5 }
                PathCurve { x: back.width - ball.width * 0.5; y: - ball.height * 0.5 }
            }
        }

        Shape {
            ShapePath {
                strokeColor: "#ff1493"
                fillColor: "transparent"
                startX: 0
                startY: back.height
                PathCurve { x: back.width * 0.8; y: back.height * 0.8 }
                PathCurve { x: back.width * 0.2; y: back.height * 0.2 }
                PathCurve { x: back.width; y: 0 }
            }
        }

        Rectangle {
            id: ball
            x: -width * 0.5
            y: back.height - height * 0.5
            width: 50
            height: width
            radius: width * 0.5
            gradient: Gradient {
                GradientStop { position: 0.20; color: "#af2020" }
                GradientStop { position: 1.00; color: "#c27131" }
            }
            transformOrigin: Item.Center
            transform: Rotation {
                axis { x: 1; y: 1; z: 0 }

                NumberAnimation on angle {
                    running: back.running
                    duration: 1000
                    loops: -1
                    from: 0
                    to: 360
                }
            }
        }

        Text {
            anchors.left: parent.left
            anchors.top: parent.top
            anchors.margins: 10
            font.pointSize: 12
            text: "FPS: " + fpsItem.fps
            color: "red"
        }
    }
}

首先我们来看下main.cpp

  1. qmlRegisterType方法: ,将会注册一个模块 an.item;组件的名字为:FpsItem
  2. QQmlApplicationEngine: 定义一个qml引擎;加载qml 文件
    再来看看qml文件:
  3. import an.item 1.0导入模块an.item
  4. FpsItem {
     id: fpsItem  }  使用组件,其中fpsItem中定义了一个属性fps可在qml中直接访问。
    
  5. 当然我们定义的FpsItem 是继承自QQuickItem的,无界面显示。如果想含有界面显示的可以继承QQuickWidget 或者是QQuickWindow 等。
  6. 这里对于Q_PROPERTY 这些QT 封装类的技巧就不在一一介绍,
  7. 感兴趣的同学可以去查阅下 Q_INVOKABLE 作为导出方法体供qml 直接使用。
  8. 关于C++ 如何与C++ 通信,下次再讲解。
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QMLC++ 交互的过程一般分为以下几个步骤: 1. 定义 C++ 类并注册到 QML 中 你需要在 C++ 中定义一个类,该类封装了你想要实现的功能。同时,你需要使用 `qmlRegisterType` 函数将该类注册到 QML 中,以便在 QML 中使用该类。 例如,你可以定义一个名为 `MyClass` 的类,并将其注册到 QML 中: ```cpp class MyClass : public QObject { Q_OBJECT public: Q_INVOKABLE int myFunction(int arg) { // 实现你的功能 } }; qmlRegisterType<MyClass>("com.example", 1, 0, "MyClass"); ``` 在上面的代码中,`Q_INVOKABLE` 用于声明 `myFunction` 函数可从 QML 中调用,`qmlRegisterType` 函数用于将 `MyClass` 类注册到 QML 中。`"com.example"` 表示注册的命名空间,`1` 和 `0` 表示主版本号和次版本号,`"MyClass"` 是在 QML 中使用的类名。 2. 在 QML 中使用 C++ 类 在 QML 中使用 C++ 类时,你需要使用 `import` 语句导入该类所在的命名空间。然后,你可以通过该命名空间来访问该类。例如: ```qml import com.example 1.0 MyClass { id: myClass } Button { onClicked: { var result = myClass.myFunction(42) // 处理返回值 } } ``` 在上面的代码中,`import` 语句用于导入 `com.example` 命名空间,`MyClass` 用于创建一个 `MyClass` 实例,`id` 属性用于设置实例的标识符,`Button` 用于创建一个按钮,`onClicked` 事件处理程序中调用了 `myFunction` 函数,并处理了它的返回值。 3. 在 C++ 中访问 QML 中的对象 如果你需要从 C++ 中访问 QML 中的对象,你可以使用 `QQuickItem` 类提供的 `findChild` 函数。例如: ```cpp QQuickItem *item = qmlEngine.rootObjects().value(0)->findChild<QQuickItem*>("myItem"); if (item) { // 处理 item 对象 } ``` 在上面的代码中,`qmlEngine.rootObjects()` 函数返回 QML 引擎中所有的根对象,`value(0)` 返回第一个根对象,`findChild` 函数用于查找名为 `"myItem"` 的子对象。 以上就是 QMLC++ 交互的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值