Пользовательский тип C++ из модуля QML не определен при использовании внутри файла QML.C++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Пользовательский тип C++ из модуля QML не определен при использовании внутри файла QML.

Сообщение Anonymous »

В моем проекте я пытаюсь предоставить одноэлементный тип QML из C++. Первоначально я зарегистрировал его с помощью qmlRegisterSingletonInstance, и все работало нормально. Но когда я попытался заменить этот способ макросами QML_ELEMENT и QML_SINGLETON, он компилируется нормально, но когда QML пытается использовать класс, он жалуется, что тип не определен.
В моем проекте есть два модуля, один состоит исключительно из файлов qml, а второй - из файлов C++, из которых я пытаюсь выставить класс и использовать его в первом модуле. Структура немного сложна, поэтому я воспроизвел проблему с помощью более простого тестового проекта. Я заметил, что QML не может распознать ни одноэлементный тип, ни не-одноэлементный тип.
Проект имеет следующую структуру:

Код: Выделить всё

│   CMakeLists.txt
│   main.cpp
│
└───logicmodule
CMakeLists.txt
Main.qml
Message.h
MySingleton.h
Код:

Код: Выделить всё

// logicmodule/MySingleton.h
#pragma once

#include 
#include 
#include 

class MySingleton : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
public:
MySingleton(QObject *parent = nullptr)
: QObject{parent}
{}

public slots:
QString exec(const QString &str) { return "somestring"; }
};

Код: Выделить всё

// logicmodule/Message.h
#pragma once

#include 
#include 
#include 

class Message : public QObject
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(QString author MEMBER m_author NOTIFY authorChanged)
public:
Message() {}

signals:
void authorChanged();

private:
QString m_author;
};

Код: Выделить всё

// logicmodule/Main.qml
import QtQuick
import QtQuick.Controls

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

// property Message msg: Message {}
Button {
id: button
anchors.centerIn: parent
text: "Click me"
onClicked: {
label.text = MySingleton.exec(label.text)
}
}
Label {
id: label
anchors.top: button.bottom
}
}

Код: Выделить всё

// logicmodule/CMakeLists.txt
project(logicmodule VERSION 0.1 LANGUAGES CXX)

qt_add_library(${PROJECT_NAME} STATIC)
qt6_add_qml_module(${PROJECT_NAME}
URI Main
VERSION 1.0
NO_PLUGIN
RESOURCE_PREFIX "/qt/qml"
QML_FILES
Main.qml
SOURCES
MySingleton.h
Message.h
)

target_link_libraries(${PROJECT_NAME} PUBLIC
Qt6::Core
Qt6::Gui
Qt6::Qml
Qt6::Quick
)

target_include_directories(${PROJECT_NAME}
PUBLIC
.
)

Код: Выделить всё

// main.cpp
#include 
#include 
#include "Message.h"
#include "MySingleton.h"

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

QQmlApplicationEngine engine;

const QUrl url(u"qrc:/qt/qml/Main/Main.qml"_qs);
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;
}

return app.exec();
}

Код: Выделить всё

// CMakeLists.txt
cmake_minimum_required(VERSION 3.16)

project(typetest VERSION 0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml)

qt_standard_project_setup(REQUIRES 6.5)

add_subdirectory(logicmodule)

qt_add_executable(apptypetest
main.cpp
)

target_link_libraries(apptypetest PUBLIC
logicmodule
)

# No effect
# target_include_directories(apptypetest
#   PUBLIC
#       "${PROJECT_SOURCE_DIR}/logicmodule"
#       logicmodule
# )
# include_directories(logicmodule)
Все компилируется нормально, но во время выполнения я получаю сообщение об ошибке при попытке вызвать MySingleton:

Код: Выделить всё

qrc:/qt/qml/Main/Main.qml:16: ReferenceError: MySingleton is not defined
Я пытался изучить эту проблему, но не смог найти именно мой случай. Самое близкое, что мне удалось найти, это следующий:
qmltyperegistration include path не подтверждает подкаталоги
Но файлы с пользовательскими типами, похоже, включаются без каких-либо префиксов.
Я также заметил, что в папке сборки у меня есть файл build\Debug\logicmodule\logicmodule_qmltyperegistrations .cpp и он содержит вызовы qmlRegisterTypesAndRevisions, но кажется, что это не имеет эффекта?
Также попробовал структуру проекта без каких-либо дополнительных библиотек (поэтому без логического модуля lib, все находится в корне проекта, и у меня есть только один CMakeLists), и он, похоже, работает нормально, и все пользовательские типы распознаются QML.
Могло бы кто-нибудь укажет мне, что я делаю не так с библиотекой? Почему QML не может распознать тип, если он определен внутри библиотеки?

Подробнее здесь: https://stackoverflow.com/questions/786 ... e-qml-file
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»