我正在尝试使用QTPropertyBrowser来编辑QObjects中的属性。 从QT Solutions“QtPropertyBrowser”示例中,我在项目中使用以下文件。
我按如下方式配置我的CMakeFile:
#include_directories("/usr/include")
SET(QTVIEW_SRCS
src/main.cpp
src/TestWidget.cpp
src/plugin/IPlugin.cpp
src/objectcontroller.cpp
)
SET(QTVIEW_MOH_HDRS
src/TestWidget.h
src/plugin/IPlugin.h
src/objectcontroller.h
)
当我按原样编译文件时,编译器会给出如下错误 -
C:\ SVN \ osaka3d \树干\ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx: 在成员函数'virtual int中 ObjectController :: qt_metacall(QMetaObject ::呼叫, int,void **)': C:\ SVN \ osaka3d \树干\ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx:73: 错误:无效使用不完整类型 'struct ObjectControllerPrivate' C:\ SVN \ osaka3d \树干\ osaka3d \ QTView \ SRC / objectcontroller.h:45: 错误:'结构的前向声明 ObjectControllerPrivate” C:\ SVN \ osaka3d \树干\ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx:73: 错误:之前的预期类型说明符 'QtProperty' C:\ SVN \ osaka3d \树干\ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx:73: 错误:预期'>'之前 'QtProperty' C:\ SVN \ osaka3d \树干\ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx:73: 错误:预期'('之前 'QtProperty' C:\ SVN \ osaka3d \树干\ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx:73: 错误:未声明'QtProperty' 在这个范围内 C:\ SVN \ osaka3d \树干\ osaka3d \ QTView \ SRC \ moc_objectcontroller.cxx:73: 错误:期望的primary-expression 之前')'令牌mingw32-make 2: * [CMakeFiles / qtview.dir / SRC / moc_objectcontroller.cxx.obj] 错误1 mingw32-make 1: [CMakeFiles / qtview.dir / all]错误2 mingw32-make:* * [all]错误2
但是当我注释掉这一行时:
Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QVariant &))
答案 0 :(得分:6)
我遇到了同样的问题(我是qt的新手,但这对我有用)。对于寻找解决方案的其他人,我发现了这个:
问题在于,由于Q_PRIVATE_SLOT
宏,生成的moc_XXX.cxx
需要XXXPrivate
类的完整声明来调用私有槽函数。由于公共头只有前向声明它,生成的cxx不能自己编译。 QtPropertyBrowser 的人通过在源文件中包含生成的moc_XXX.cpp
(请注意'pp',cmake生成'xx'))来避免这个问题(丑陋,但有效)。我也不知道任何其他方式告诉 moc 包含(在这种情况下甚至不存在)私有XXX_p.hpp
。所以我们坚持这样。
接下来我要做的是从可执行文件中删除生成的moc_XXX.cxx
文件,但这导致 moc 永远不会被调用。即使我使用QT4_WRAP_CPP
,也会发生这种情况。所以在进一步搜索后我发现......
此特例的一个附录:缺少QtProperty
声明。添加以下前向声明或相应的包含文件:
#if QT_VERSION >= 0x040400
QT_BEGIN_NAMESPACE
#endif
class QtProperty;
#if QT_VERSION >= 0x040400
QT_END_NAMESPACE
#endif
完全归功于提出此cmake功能的 fullmetalcoder :
function(qt4_wrap_hdrs _moc_srcs)
qt4_get_moc_flags(_moc_incs)
set(_mocs)
foreach(_current_file ${ARGN})
get_filename_component(_abs_file ${_current_file} ABSOLUTE)
if(EXISTS ${_abs_file})
file(READ ${_abs_file} _contents)
get_filename_component(_basename ${_abs_file} NAME_WE)
string(REGEX MATCH "Q_OBJECT" _match "${_contents}")
if(_match)
set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp")
qt4_create_moc_command(${_abs_file} ${_moc} "${_moc_incs}" "")
macro_add_file_dependencies(${_abs_file} ${_moc})
list(APPEND _mocs ${_moc})
endif(_match)
endif(EXISTS ${_abs_file})
endforeach (_current_file)
set(${_moc_srcs} ${_mocs} PARENT_SCOPE)
endfunction(qt4_wrap_hdrs)
(来自http://www.qtcentre.org/threads/37428-using-QT-unit-testing-with-CMake)
您可以将此功能用作QT4_WRAP_CPP
的替代品。您现在只需要将以下行添加到CMakeLists.txt中,以便编译器找到生成的moc_XXX.cpp
文件(新函数创建了'pp'文件...):
include_directories(${CMAKE_BINARY_DIR})
此函数一直调用 moc ,其行为更像 qmake 中的情况。当然,除了您可以轻松完成源代码构建。
但有一点需要注意:所有moc_XXX.cpp
文件都是在CMAKE_BINARY_DIR
中生成的。因此,如果您有两个文件include1/foo.hpp
和include2/foo.hpp
,则会覆盖一个文件!
答案 1 :(得分:1)
您是否阅读了以下关于一起使用Qt和CMake的文章?
http://developer.qt.nokia.com/quarterly/view/using_cmake_to_build_qt_projects
也许你忘记了某些事情,比如在你的CMakeLists.txt上调用QT4_WRAP_CPP
。