qmltyperegistration 包含路径不承认子目录

Moh*_* Li 4 c++ cmake qml

我正在尝试使用 qml 构建一个 Qt 项目。qml 元类型注册仅查看顶级 qml 目录。我也想让它查看子目录。

该项目的结构如下:

./CMakeLists.txt
./ui
./ui/MainWindow.qml
./src
./src/controller
./src/controller/Foo.cpp
./src/controller/FileController.cpp
./src/controller/FileController.h
./main.cpp
Run Code Online (Sandbox Code Playgroud)

我的 CMakeLists.txt 如下所示:

cmake_minimum_required(VERSION 3.25)
project(testproject)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick Widgets)

qt_standard_project_setup()

qt_add_executable(testproject)
target_sources(testproject PRIVATE 
    main.cpp
)


target_link_libraries(testproject PRIVATE 
    Qt6::Widgets
    Qt6::Gui 
    Qt6::Quick 
)

set_target_properties(testproject PROPERTIES
        CXX_STANDARD 17
        CXX_STANDARD_REQUIRED ON
        CXX_EXTENSIONS OFF
        OUTPUT_NAME some_test_exec
)

target_include_directories(testproject PUBLIC ${PROJECT_SOURCE_DIR}/include)


qt_add_qml_module(testproject
        URI testproject
        VERSION 1.0
        SOURCES
            src/controller/FileController.h
            src/controller/FileController.cpp
        QML_FILES
            ui/MainWindow.qml
)
Run Code Online (Sandbox Code Playgroud)

我有一个启动应用程序的主函数:

#include <iostream>
#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char* argv[]) {
    QGuiApplication app(argc, argv);
    QQmlApplicationEngine engine;
    const QUrl url(u"qrc:/testproject/ui/MainWindow.qml"_qs);
    engine.load(url);
    return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

我在 MainWindow.qml 中创建了一个简单的 qml 文件

ui/MainWindow.qml
Run Code Online (Sandbox Code Playgroud)

看起来像这样:

import QtQuick
import QtQuick.Controls

ApplicationWindow {
    id: mainwindow
    visible: true
    width: 640
    height: 480
    menuBar: MenuBar {
        Menu {
            title: "File"
            MenuItem { text: "open" }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在里面

src/controller
Run Code Online (Sandbox Code Playgroud)

子目录中,我创建以下头文件 FileController.h

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

class FileController : public QObject {
    Q_OBJECT
    QML_ELEMENT // WITHOUT THIS IT COMPILES FINE
    Q_PROPERTY(QString file  READ name WRITE setName NOTIFY filenameChanged)
private:
    QString filename;
    void setName(QString name);
public:
    FileController(QObject *parent);
    QString name();
signals:
    void filenameChanged();
};
Run Code Online (Sandbox Code Playgroud)

以及 FileController.cpp 中的一些实现细节

#include "FileController.h"

FileController::FileController(QObject *parent) : QObject(parent) {}

void FileController::setName(QString name) {filename = name;}

QString FileController::name() {return filename;}
Run Code Online (Sandbox Code Playgroud)

编译时,我收到以下错误:

[13/19] Building CXX object CMakeFiles/test....dir/testproject_qmltyperegistrations.cpp.o
FAILED: CMakeFiles/testproject.dir/testproject_qmltyperegistrations.cpp.o 
/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_QMLINTEGRATION_LIB -DQT_QMLMODELS_LIB -DQT_QML_LIB -DQT_QUICK_LIB -DQT_WIDGETS_LIB -I/some/test/directory/build/testproject_autogen/include -I/ome/test/directory/include -I/some/test/directory -isystem /usr/include/qt6/QtQml/6.4.1 -isystem /usr/include/qt6/QtQml/6.4.1/QtQml -isystem /usr/include/qt6/QtCore/6.4.1 -isystem /usr/include/qt6/QtCore/6.4.1/QtCore -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtQml -isystem /usr/include/qt6/QtQmlIntegration -isystem /usr/include/qt6/QtNetwork -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtQuick -isystem /usr/include/qt6/QtQmlModels -isystem /usr/include/qt6/QtOpenGL -fPIC -std=c++17 -MD -MT CMakeFiles/testproject.dir/testproject_qmltyperegistrations.cpp.o -MF CMakeFiles/testproject.dir/testproject_qmltyperegistrations.cpp.o.d -o CMakeFiles/testproject.dir/testproject_qmltyperegistrations.cpp.o -c /some/test/directory/build/testproject_qmltyperegistrations.cpp
/some/test/directory/qt/qml_in_other_dir/build/testproject_qmltyperegistrations.cpp:10:10: fatal error: FileController.h: No such file or directory
   10 | #include <FileController.h>
Run Code Online (Sandbox Code Playgroud)

显然,在注册 qml 元类型时,Qt 不会在子目录中查找相应的标头。或者它应该复制它们,但没有。它的包含路径中的目录中没有 FileController.h。

  1. 为什么 CMake 和 Qt 不保留目录结构?
  2. 我想在 qml 文件中有一些逻辑(特别是在这里打开一个文件对话框并将结果传递给 C++ 类)。为了让 qml 和 C++ 交互,我需要使用 QML_ELEMENT 宏注册该类。我是否在做一些根本性错误的事情?这样做的正确方法是什么?(我总是可以摆弄包含路径或将所有内容放在基本目录中,但这似乎是错误的)。

编辑:问题仍然发生,例如将 Filecontroller.h 放入

./include/controller/
Run Code Online (Sandbox Code Playgroud)

并添加

include
Run Code Online (Sandbox Code Playgroud)

到 target_include_directories 并将 FileController.cpp 中的包含路径调整为类似的内容

#include <controller/FileController.h>
Run Code Online (Sandbox Code Playgroud)

iam*_*ter 6

您需要添加include_directories(src/controller)到 CMake 文件或将包含设置为#include <src/controller/FileController.h>.

看看这个SO问题

编辑:我发现这些错误报告QTBUG-87221QTBUG-101146。该补丁在文档中添加了一条注释:

声明 QML 类型的所有标头都需要可以访问,而无需从项目的包含路径中添加任何前缀。