简体   繁体   English

如何用qt_add_qml_module注册CMake中的QObject class?

[英]How to register QObject class in CMake with qt_add_qml_module?

I have a QObject derived class Expense that I use in QML like this.我有一个QObject派生的 class 我在 QML 中使用的Expense是这样的。

// main.qml
Expense {
  id: expenseManager
  onExpenseCreated: {
      // Do something
  }
}

The expense class has no UI components, it has some basic Signal and Slots for API communications.费用 class 没有 UI 组件,它有一些用于 API 通信的基本信号和插槽。

// expense.h

#ifndef EXPENSE_H
#define EXPENSE_H
#include <QObject>
#include <QString>

#include "service.h"

class Expense : public QObject
{
    Q_OBJECT

private:
    Service service;
    void networkError();
    bool buttonLock = false;

public:
    explicit Expense(QObject *parent = nullptr);


public slots:
    void createInvoice(QString item, float amount);

signals:
    void expenseCreated();

};

#endif // EXPENSE_H

I have used qmlRegisterType() for registering Expense type in QML. Below is how my main() looks like.我已经使用qmlRegisterType()在 QML 中注册Expense类型。下面是我的main()的样子。

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    ......


    qmlRegisterType<Expense>("com.kadbyte.expense", 1, 0, "Expense");

    ........
    return app.exec();
}

Everything working perfectly as it used to.一切都像以前一样完美地工作。 But recently I have upgraded my project to QT6 with CMake as the build tool instead of QMake.但最近我将我的项目升级到 QT6,使用 CMake 作为构建工具而不是 QMake。 In the docs I saw that we can use qt_add_qml_module command in CMakeList.txt to register C++ Classes instead of qmlRegisterType() , by adding QML_ELEMENT macro to the QObject class.在文档中我看到我们可以在 CMakeList.txt 中使用qt_add_qml_module命令来注册 C++ 类而不是qmlRegisterType() ,方法是将QML_ELEMENT宏添加到 QObject class。

But I can't understand how to do this, the documentation doesn't make sense as it uses qmake example ( Link to docs ) instead of CMake. Below is my CMakeLists.txt file但我不明白该怎么做,文档没有意义,因为它使用 qmake 示例( 链接到文档)而不是 CMake。下面是我的 CMakeLists.txt 文件

cmake_minimum_required(VERSION 3.16)

project(Udyan VERSION 0.1 LANGUAGES CXX)

set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 6.2 COMPONENTS Quick REQUIRED)

qt_add_executable(appUdyan
    main.cpp
    expense.h expense.cpp
)

qt_add_qml_module(appUdyan
    URI Udyan
    VERSION 1.0
    QML_FILES qml/main.qml
)

set_target_properties(appUdyan PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)

target_compile_definitions(appUdyan
    PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)

target_link_libraries(appUdyan
    PRIVATE Qt6::Quick)

So how to use qt_add_qml_module to registering QObject class to use in QML?那么如何使用qt_add_qml_module将QObject class注册到QML中使用呢?

Note: All the example I have given above is just an MRE and not my complete code.注意:我上面给出的所有示例只是一个 MRE,而不是我的完整代码。

You just need to add QML_ELEMENT to your QObject-derived Expense class's header and make sure you have moc enabled in your CMakeLists.txt.您只需将QML_ELEMENT添加到 QObject 派生的Expense类的 header 中,并确保在 CMakeLists.txt 中启用了 moc。 In application case it doesn't matter if the expense.h/cpp sources are included via qt_add_executable or qt_add_qml_module .在应用案例中,expense.h/cpp 源是否通过qt_add_executableqt_add_qml_module包含并不重要。 I think it's clearer to add them to qt_add_qml_module SOURCES .我认为将它们添加到qt_add_qml_module SOURCES会更清楚。 Then you just import module URI in you QML file.然后你只需在 QML 文件中导入模块 URI。 In the example below I'm printing out property value from Expense object in QML.在下面的示例中,我从 QML 中的 Expense object 中打印出属性值。

CMakeLists.txt CMakeLists.txt

set(CMAKE_AUTOMOC ON)

qt_add_qml_module(appUdyan
    URI udyan
    VERSION 1.0
    QML_FILES
        main.qml
    SOURCES
        expense.h
        expense.cpp
)

C++ C++

#include <QObject>
#include <QtQml/qqmlregistration.h>

class Expense : public QObject
{
    Q_OBJECT
    QML_ELEMENT
    Q_PROPERTY(int value READ value NOTIFY valueChanged)
public:
    explicit Expense(QObject *parent = nullptr);
    int value() const;

signals:
    void valueChanged();

private:
    int m_value {5};
};

QML: QML:

import QtQuick
import udyan

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Expense {
        id: expense
        Component.onCompleted: console.log(expense.value)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM