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

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

Qt QML app crashing using gadgets defined in a library

问题

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

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

  1. #include <QMetaType>
  2. Q_DECLARE_METATYPE(Bar)

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

  1. 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:

  1. cmake_minimum_required(VERSION 3.16)
  2. project(foo VERSION 0.1 LANGUAGES CXX)
  3. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  4. find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
  5. qt_standard_project_setup(REQUIRES 6.5)
  6. set(SOURCES
  7. # cmake-format: sort
  8. main.cpp
  9. foo.cpp
  10. fooobjectwithbarproperty.cpp
  11. )
  12. set(HEADER
  13. # cmake-format: sort
  14. fooobjectwithbarproperty.h
  15. foo.h
  16. )
  17. qt_add_executable(appfoo
  18. main.cpp
  19. )
  20. qt_add_qml_module(appfoo
  21. URI foo
  22. VERSION 1.0
  23. QML_FILES Main.qml
  24. SOURCES
  25. ${SOURCES}
  26. ${HEADER}
  27. )
  28. set_target_properties(appfoo PROPERTIES
  29. MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
  30. MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
  31. MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
  32. MACOSX_BUNDLE TRUE
  33. WIN32_EXECUTABLE TRUE
  34. )
  35. target_link_libraries(appfoo
  36. PUBLIC Qt6::Quick bar
  37. )
  38. install(TARGETS appfoo
  39. BUNDLE DESTINATION .
  40. LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
  41. RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
  42. )

bar CMakeLists:

  1. cmake_minimum_required(VERSION 3.14)
  2. project(bar LANGUAGES CXX)
  3. set(CMAKE_AUTOUIC ON)
  4. set(CMAKE_AUTOMOC ON)
  5. set(CMAKE_AUTORCC ON)
  6. set(CMAKE_CXX_STANDARD 17)
  7. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  8. find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
  9. find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
  10. add_library(bar SHARED
  11. bar_global.h
  12. bar.cpp
  13. bar.h
  14. )
  15. target_link_libraries(bar PRIVATE Qt${QT_VERSION_MAJOR}::Core)
  16. target_compile_definitions(bar PRIVATE BAR_LIBRARY)

top-level CMakeLists:

  1. cmake_minimum_required(VERSION 3.26.0)
  2. project(
  3. FooBar
  4. VERSION 0.0.1
  5. DESCRIPTION &quot;Demo for Qt issue&quot;
  6. LANGUAGES CXX)
  7. set(CMAKE_CXX_STANDARD 20)
  8. add_subdirectory(foo)
  9. add_subdirectory(bar)

My QObject, defined in foo, looks like this:

  1. class FooObjectWithBarProperty : public QObject
  2. {
  3. Q_OBJECT
  4. Q_PROPERTY(Bar bar READ getBar WRITE setBar NOTIFY barChanged)
  5. Q_PROPERTY(Foo foo READ getFoo WRITE setFoo NOTIFY fooChanged)
  6. public:
  7. const Bar getBar() const {
  8. return _bar;
  9. }
  10. void setBar(const Bar&amp; bar) {
  11. _bar = bar;
  12. emit barChanged(_bar);
  13. }
  14. const Foo getFoo() const {
  15. return _foo;
  16. }
  17. void setFoo(const Foo&amp; foo) {
  18. _foo = foo;
  19. emit fooChanged(_foo);
  20. }
  21. private:
  22. Bar _bar;
  23. Foo _foo;
  24. signals:
  25. void barChanged(const Bar&amp;);
  26. void fooChanged(const Foo&amp;);
  27. };

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

  1. struct Foo
  2. {
  3. Q_GADGET
  4. Q_PROPERTY(double x MEMBER x)
  5. Q_PROPERTY(double y MEMBER y)
  6. public:
  7. double x, y;
  8. };

Given the following setup in main.cpp:

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

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

  1. Text {
  2. anchors.centerIn: parent
  3. text: obj.foo.x
  4. }

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文件中的这行代码:

  1. find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)

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

  1. /****************************************************************************
  2. ** Meta object code from reading C++ file 'bar.h'
  3. **
  4. ** 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:

  1. 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:

  1. /****************************************************************************
  2. ** Meta object code from reading C++ file &#39;bar.h&#39;
  3. **
  4. ** 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:

确定