将 somedialog.h 包含在项目的其他部分中会使编译器看不到 ui_somedialog.h
including somedialog.h into other parts of the project makes ui_somedialog.h invisible to compiler
我正在尝试在项目中以不同的方式使用自定义Qt对话框。有两种情况,其中会出现相同的问题。
1.我将对话框作为库包含在主项目中。该库是一个更大的subdirs项目的一部分,该项目还包含将使用它的主应用程序。下面是项目树:
AppProject
|_AppProject.pro
|_MyApp
|_myapp.pro
|_main.cpp
|_mainwindow.h
|_mainwindow.cpp
|_mainwindow.ui
|_GUILib
|_guilib.pro
|_guilib_decl.h
|_somedialog.h
|_somedialog.cpp
|_somedialog.ui
源文件在这里:
main.cpp mainwindow.h mainwindow.cpp guilib_decl.h somedialog.h somedialog.cpp
somedialog.ui
AppProject 是一个普通的子项目,包括 MyApp 和 GUILib:
TEMPLATE = subdirs
SUBDIRS += MyApp
GUILib
MyApp.depends = GUILib
我的应用是一个普通的应用模板:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = MyApp
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
CONFIG += c++14
DEPENDPATH += ../GUILib
INCLUDEPATH += ../GUILib
LIBS += -L../GUILib -lGUILib
HEADERS += mainwindow.h
SOURCES += main.cpp
mainwindow.cpp
FORMS += mainwindow.ui
这是 lib 项目文件:
QT += core widgets gui
TARGET = GUILib
TEMPLATE = lib
CONFIG += c++14
CONFIG -= debug_and_release
DEFINES += QT_DEPRECATED_WARNINGS
DEFINES += GUILIB_LIBRARY
HEADERS +=
guilib_decl.h
somedialog.h
SOURCES +=
guilib.cpp
somedialog.cpp
FORMS +=
somedialog.ui
该库可以自己构建(没有问题,找到ui_somedialog.h(,但是如果我将somedialog.h包含在mainwindow.h中,那么编译器会弹出以下错误消息:
ui_somedialog.h:没有这样的文件或目录
阿拉伯数字。我将对话框作为非库包含在测试中。
这里的项目树如下所示:
AppProject
|_AppProject.pro
|_MyApp
|_myapp.pro
|_main.cpp
|_mainwindow.h
|_mainwindow.cpp
|_mainwindow.ui
|_somedialog.h
|_somedialog.cpp
|_somedialog.ui
|_Tests
|_tests.pro
|_main.cpp
|_tst_somedialog.cpp
它仍然是一个subdirs项目,但这次其中一个是测试项目,对话框只是应用程序的正常部分(非lib(。
测试的项目文件如下所示:
QT += testlib
QT += widgets gui
TARGET = Tests
TEMPLATE = app
CONFIG += c++14
CONFIG += testcase
CONFIG -= debug_and_release
INCLUDEPATH += ../MyApp
SOURCES += main.cpp
tst_somedialog.cpp
不幸的是,对话框是否是 lib 似乎并不重要,在这两种情况下,编译器都会显示相同的错误消息。最有趣的部分是,ui 文件是它应该在的位置(uic 完成了它的工作(,所以理论上编译器应该在这两种情况下都能找到它,但由于某种原因它没有。有什么我不知道的秘密可以让它工作吗?为什么当我尝试在其他地方使用它时,编译器看不到 ui_somedialog.h?
谢谢。
编辑:修改为包括方案2。
编辑 2:为方案 1 添加了源文件。
最好的选择是将所有 gui 保留在主应用程序中,但由于这并不总是一个选项,请进一步阅读。
首先,我想提到发生这种情况的原因,这是因为GUILib/GeneratedFiles
(或任何Qt工具配置为放置uic
生成的文件的路径(不在MyApp的INCLUDEPATH
中,一个快速的技巧是将该路径添加到INCLUDEPATH
,但这会使事情进一步复杂化,例如如果您想部署库, 您需要确保将工具配置为在所有平台上以相同路径创建文件,因此不建议使用解决方案。
一个更好的解决方案是创建一个使用 PIMPL 包装对话框的类,基本上从所有外部源中,您只包含包含 PIMPL"接口"的标头。
注意:使用QObject
父级负责删除其子级,因此为避免双重删除,请不要使用std::unique_ptr
以防您将父级设置为对话框。
乐: 或者第 3 个选项(实际上这只是 PIMPL,所以从技术上讲它仍然是第二个选项(是避免将生成的文件 (ui_somedialog.h( 包含在 somedialog.h(您使用库的位置包含的标头(,请参阅此处的文档了解如何将 uic 生成的代码使用到C++代码中(查看Using a Pointer Member Variable
(。
//somedialog.h
#include <QWidget>
//notice there is no include for ui_somedialog.h
namespace Ui {
// forward reference for the generated class
class SomeDialog;
}
class SomeDialog : public QWidget
~SomeDialog();
//...
private:
//member pointer to the generated class
Ui::SomeDialog* ui;
}
//某对话.cpp
#include "somedialog.h"
//here we have the include for ui_somedialog.h
#include "ui_somedialog.h"
SomeDialog::SomeDialog(QWidget *parent) :
QWidget(parent), ui(new Ui::SomeDialog)
{
ui->setupUi(this);
}
SomeDialog::~SomeDialog()
{
delete ui;
}
这是一种类似于 PIMPL 的方法,您只需向前引用内部类并将接口导出到其中。
有一种方法可以设置您希望Qt工具为您生成代码的方法,但是我现在找不到它,对我来说,当前的工具似乎总是使用这种成员指针方法。
- C/C++编译器通常会删除重复的库吗
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- Win32编译器选项和内存分配
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++,我收到一个无法理解的编译器错误
- 在线编译器中的分段C++没有打印消息
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- C/C++预处理器是否可以检测一些编译器选项
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 我需要知道编译器如何在cpp中使用析构函数
- 编译器如何区分std::vector的构造函数
- CLANG 编译器 说:变量"PTR"可能未初始化
- 告诉c++编译器该参数没有别名
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么所有C++编译器都会崩溃或挂起此代码
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 我收到同义重复编译器错误。我应该如何修复"类型"X"的参数与类型"X"的参数不兼容?
- 将 somedialog.h 包含在项目的其他部分中会使编译器看不到 ui_somedialog.h