将 somedialog.h 包含在项目的其他部分中会使编译器看不到 ui_somedialog.h

including somedialog.h into other parts of the project makes ui_somedialog.h invisible to compiler

本文关键字:somedialog 编译器 ui 看不到 其他部 包含 项目      更新时间:2023-10-16

我正在尝试在项目中以不同的方式使用自定义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工具为您生成代码的方法,但是我现在找不到它,对我来说,当前的工具似乎总是使用这种成员指针方法。