动态使用 QGLWidget 或 QOpenGLWidget,具体取决于 Qt 版本
Dynamically use QGLWidget or QOpenGLWidget depending on Qt version
我的代码应该在Qt 5.4之前和之后的平台上编译和运行,其中引入了QOpenGLWidget,取代了QGLWidget。我想我可以编写这样的代码来支持两者:
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
# define USE_Q_OPEN_GL_WIDGET
#endif
#ifdef USE_Q_OPEN_GL_WIDGET
# include <QOpenGLWidget>
#else
# include <QGLWidget>
#endif
class GLWidget :
#ifdef USE_Q_OPEN_GL_WIDGET
public QOpenGLWidget
#else
public QGLWidget
#endif
{
Q_OBJECT
public:
[...]
但这不会成功,因为moc
似乎不理解预处理器指令,并且会为错误的类生成代码。
我试图通过向我的CMakeLists.txt
添加一个 add_custom_command
指令来解决此问题,该指令将在文件传递到 moc 之前${CMAKE_CXX_COMPILER}" -E -P -x c++-header ...
上运行。但这似乎也不起作用,因为预处理器将删除魔术Q_OBJECT
行,表明确实必须在运行 C 预处理器之前运行moc
。
我还有哪些其他选择?
我是否必须诉诸于两个几乎相同的头文件(两行除外),然后在 cmake 中构建时选择正确的一个?
编辑
若要测试此问题,请尝试以下操作:
- 在 qt 5.2.1 附带的 Ubuntu 可信系统上(您可以使用
sudo debootstrap trusty ubuntu-trusty
创建 chroot) 执行以下操作: - apt-get install libqt5opengl5-dev build-essential qttools5-dev qt5-default
然后创建包含以下内容的
glwidget.h
:#ifndef GLWIDGET_H #define GLWIDGET_H #include <QtGlobal> #if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) # define USE_Q_OPEN_GL_WIDGET #endif #ifdef USE_Q_OPEN_GL_WIDGET # include <QOpenGLWidget> #else # include <QGLWidget> #endif class GLWidget : #ifdef USE_Q_OPEN_GL_WIDGET public QOpenGLWidget #else public QGLWidget #endif { Q_OBJECT }; #endif
然后运行:
$ moc -v moc 5.2.1 $ moc glwidget.h | grep QGL || echo "not found" not found $ moc glwidget.h | grep QOpenGL >/dev/null && echo "found!" found!
所以你会看到,即使Qt 5.2.1没有QOpenGL,moc也会以这种方式解释预处理器指令
。我们可以将版本检查更改为更简单的
#if QT_VERSION >= 0x050400
如果我们再次尝试该检查,那么 Ubuntu 中 Qt 5.2.1 中的 moc 信任会生成正确的结果
因此,我们认为我们找到了解决方案,并尝试在同一代码上运行来自更新的Qt发行版的MOC。这次我在 Debian 不稳定中使用 qt 5.5.1 的 moc,我得到:
$ moc -v moc 5.5.1 $ moc glwidget.h | grep QOpen || echo "not found" not found $ moc foo.h | grep QGL > /dev/null && echo "found" found
最有趣的是,如果在 qt 5.5.1 下我将版本检查宏 mack 转换为使用
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
那么它确实有效!
因此,总而言之,moc 确实理解一些预处理器指令,但它理解的指令在 qt 5.4 之前和之后的版本之间是不同的。似乎不存在双方都能理解的通用预处理器指令。因此,我看不到使用预处理器指令解决此问题的方法。
可以使用 CMake 生成此标头。把这段代码放进去:
#include <@GL_CLASS@>
class GLWidget : @GL_CLASS@
{
Q_OBJECT
public:
[...]
然后在CMakeLists.txt中执行此操作:
set(GL_CLASS <depending on Qt version>)
include_directories(${CMAKE_CURRENT_BINARY_DIR}) #this is because configure_file produces its output in the build dir
configure_file(yourheader.h output.h @ONLY)
最后,在代码中使用#include "output.h"
。
- Qt VTK交互风格的信号到小部件
- QT在错误的班级中寻找空位
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 如何在Qt窗口小部件中使用QStringView(或QStringRef)
- 如何在Qt C++中更改光标
- 如何在MS Visual Studio 2019中运行QT UI
- QT通过C++添加映射QML项目
- libssh 的函数在构建 libssh 时无法在 Qt 和 cmake 错误中找到
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 使用Qt C++计算类似Git的SHA1哈希
- Qt focusObjectChanged example?
- 如何在cpp文件之间切换窗口?在Qt中
- 重载运算符new[]的行为取决于析构函数
- Qt和C++:将QLineEdit添加到QTabWidget中
- 从数据库实时显示QT c++中的数据
- Qt Quick-如何仅从c++代码与qml属性交互
- 无法使用Qt Creator在Windows中构建yaml-cpp
- 动态使用 QGLWidget 或 QOpenGLWidget,具体取决于 Qt 版本
- 包含指令取决于Qt版本