QML与C++ 交互详解

这里写自定义目录标题

  • QML与C++ 交互详解
    • (一) QML如何访问C++ 类:

QML与C++ 交互详解

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

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

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

#include 
#include 

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 

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 
#include 

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++ 通信,下次再讲解。

你可能感兴趣的:(QML,学习,c++,交互,qt)