Qt QML应用程序在使用库中定义的小部件时崩溃。

huangapple go评论75阅读模式
英文:

Qt QML app crashing using gadgets defined in a library

问题

在你提供的代码和描述中,问题似乎出现在你尝试使用QML中的obj.bar.x时,应用程序崩溃,而不是obj.foo.x。根据你提供的信息,这可能是由于Bar类型没有正确注册为Qt元类型而引起的。

为了正确注册Bar类型,你可以在foo项目的代码中添加以下行:

#include <QMetaType>
Q_DECLARE_METATYPE(Bar)

然后,在main.cppmain函数之前,添加以下行,以确保Bar类型在使用前已注册:

qRegisterMetaType<Bar>();

这应该解决你遇到的问题,因为它会正确注册Bar类型,以便在QML中使用它。如果问题仍然存在,可能需要仔细检查项目的配置和代码,确保没有其他问题导致崩溃。

英文:

Given two CMake subprojects: foo and bar, I want to define Q_GADGET in bar and use it in foo, but the application crashes when accessing a QObject property of type Bar (defined in bar project).

foo CMakeLists, created by QtCreator, I just added SOURCES / HEADER and added bar to target_link_libraries:

cmake_minimum_required(VERSION 3.16)

project(foo VERSION 0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)

qt_standard_project_setup(REQUIRES 6.5)

set(SOURCES
    # cmake-format: sort
    main.cpp
    foo.cpp
    fooobjectwithbarproperty.cpp
)

set(HEADER
    # cmake-format: sort
    fooobjectwithbarproperty.h
    foo.h
)

qt_add_executable(appfoo
    main.cpp
)

qt_add_qml_module(appfoo
    URI foo
    VERSION 1.0
    QML_FILES Main.qml
    SOURCES
        ${SOURCES}
        ${HEADER}
)

set_target_properties(appfoo 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_link_libraries(appfoo
    PUBLIC Qt6::Quick bar
)

install(TARGETS appfoo
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}

)

bar CMakeLists:

cmake_minimum_required(VERSION 3.14)

project(bar LANGUAGES CXX)


set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)

add_library(bar SHARED
  bar_global.h
  bar.cpp
  bar.h
)

target_link_libraries(bar PRIVATE Qt${QT_VERSION_MAJOR}::Core)

target_compile_definitions(bar PRIVATE BAR_LIBRARY)

top-level CMakeLists:

cmake_minimum_required(VERSION 3.26.0)

project(
    FooBar
    VERSION 0.0.1
    DESCRIPTION &quot;Demo for Qt issue&quot;
    LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)

add_subdirectory(foo)
add_subdirectory(bar)

My QObject, defined in foo, looks like this:

class FooObjectWithBarProperty : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Bar bar READ getBar WRITE setBar NOTIFY barChanged)
    Q_PROPERTY(Foo foo READ getFoo WRITE setFoo NOTIFY fooChanged)

public:
    const Bar getBar() const {
        return _bar;
    }

    void setBar(const Bar&amp; bar) {
        _bar = bar;
        emit barChanged(_bar);
    }

    const Foo getFoo() const {
        return _foo;
    }

    void setFoo(const Foo&amp; foo) {
        _foo = foo;
        emit fooChanged(_foo);
    }

private:
    Bar _bar;
    Foo _foo;

signals:
    void barChanged(const Bar&amp;);
    void fooChanged(const Foo&amp;);
};

Foo is defined in foo, while Bar is defined in Bar, they both look exactly the same:

struct Foo
{
    Q_GADGET
    Q_PROPERTY(double x MEMBER x)
    Q_PROPERTY(double y MEMBER y)

public:
    double x, y;
};

Given the following setup in main.cpp:

QQmlApplicationEngine engine;
engine.rootContext()-&gt;setContextProperty(&quot;obj&quot;, new FooObjectWithBarProperty());

I added a Text item into my Main.qml that looks like this:

Text {
    anchors.centerIn: parent
    text: obj.foo.x
}

This correctly displays 0. If I change the binding too obj.bar.x the app crashes:
Qt QML应用程序在使用库中定义的小部件时崩溃。

Stacktrace here suggest the metatype for Bar is not correctly registered, but I don't know how to correctly register it. I've tried qRegisterMetaType<Bar>, Q_DECLARE_METATYPE(Bar) in both foo or bar, I experimented a bit with QML_FOREIGN, but the docs are very sparse on it. All to no avail.

What is the necessary change here, and why?

Repo for this is available at https://github.com/marcinjakubowski/foo_bar_qt_issue

答案1

得分: 0

由于bar的CMakeLists文件中的这行代码:

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)

它会寻找Qt6和Qt5,并且由于某些原因选择了Qt5来生成moc(元对象编译器)文件,这也可以从生成的moc_bar.cpp文件中看出:

/****************************************************************************
** Meta object code from reading C++ file 'bar.h'
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.15.9)

将这行代码中的Qt5移除然后重新构建项目,问题就解决了。

英文:

As it turns out, it's because of this line in bar's CMakeLists:

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)

It looks for Qt6 and Qt5, and, for some reason, picks Qt5 to generate moc files, as evidenced by the resulting moc_bar.cpp:

/****************************************************************************
** Meta object code from reading C++ file &#39;bar.h&#39;
**
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.15.9)

Removing Qt5 from that find_package call and rebuilding the project makes it all work fine.

huangapple
  • 本文由 发表于 2023年5月18日 00:21:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76274226.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定