问题来源:
我用MainWindow作为主界面,Dialog作为设置界面,还需要一个AboutDialog作为关于界面。
设置界面的Dialog头文件dialog.h是这样的:
// dialog.h #ifndef DIALOG_H #define DIALOG_H #include <QDialog> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); private slots: void ApplyConnect(); private: Ui::Dialog *ui; }; #endif // DIALOG_H
dialog.cpp文件如下:
// dialog.cpp #include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(ApplyConnect())); } Dialog::~Dialog() { delete ui; } void Dialog::ApplyConnect() { //函数体 }
我又新建了一个Dialog,ui对象命名为aboutDialog,头文件aboutdialog.h仿照上面Dialog的头文件:
// aboutdialog.h #ifndef ABOUTDIALOG_H #define ABOUTDIALOG_H #include <QDialog> namespace Ui { class AboutDialog; }
class AboutDialog : public QDialog { Q_OBJECT public: AboutDialog(QWidget *parent = 0); ~AboutDialog(); private: Ui::AboutDialog *ui; private slots: void close(); }; #endif // ABOUTDIALOG_H
相应的,aboutdialog.cpp也仿照Dialog的cpp文件:
// aboutdialog.cpp #include "aboutdialog.h" #include "ui_aboutdialog.h" AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::AboutDialog) { ui->setupUi(this); connect(ui->Close_pushButton, SIGNAL(clicked()),this, SLOT(close())); } AboutDialog::~AboutDialog() { delete ui; } //关闭 void AboutDialog::close() { this->close(); }
理论上,因为Dialog的头文件和cpp文件我是仿照MainWindow的相应文件修改而来的,没出现问题,料想新建两个Dialog也不会出现问题。
编译后:
后来上网查了很多资料都没有结果。
终于,还是发现点了苗头。我开始思考,ui文件是怎么和cpp文件耦合的?
首先,dialog.ui文件会自动生成一个ui_dialog.h的头文件,相应的,aboutdialog.ui也会生成ui_aboutdialog.h的头文件,在这个头文件中,定义了setupUi以及namespace继承这些内容。这些内容关乎到一下两处:
namespace Ui { class AboutDialog; } Ui::AboutDialog*ui;
这是ui_aboutdialog.h:
/******************************************************************************** ** Form generated from reading UI file 'aboutdialog.ui' ** ** Created by: Qt User Interface Compiler version 5.2.1 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ #ifndef UI_ABOUTDIALOG_H #define UI_ABOUTDIALOG_H #include <QtCore/QVariant> #include <QtWidgets/QAction> #include <QtWidgets/QApplication> #include <QtWidgets/QButtonGroup> #include <QtWidgets/QDialog> #include <QtWidgets/QHeaderView> #include <QtWidgets/QPushButton> QT_BEGIN_NAMESPACE class Ui_aboutDialog { public: QPushButton *Close_pushButton; void setupUi(QDialog *aboutDialog) { if (aboutDialog->objectName().isEmpty()) aboutDialog->setObjectName(QStringLiteral("aboutDialog")); aboutDialog->resize(548, 479); Close_pushButton = new QPushButton(aboutDialog); Close_pushButton->setObjectName(QStringLiteral("Close_pushButton")); Close_pushButton->setGeometry(QRect(240, 370, 131, 41)); retranslateUi(aboutDialog); QMetaObject::connectSlotsByName(aboutDialog); } // setupUi void retranslateUi(QDialog *aboutDialog) { aboutDialog->setWindowTitle(QApplication::translate("aboutDialog", "Dialog", 0)); Close_pushButton->setText(QApplication::translate("aboutDialog", "Close", 0)); } // retranslateUi }; namespace Ui { class aboutDialog: public Ui_aboutDialog {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_ABOUTDIALOG_H
如果出问题也应该是这里出问题。我已开始以为是namespace冲突问题,后来通过网上找资料发现:
ui文件会根据designer中Dialog的ObjectName来生成ui_xxx.h头文件。而ui_xxx.h又是搭在ui文件和cpp文件中间不可或缺的桥梁,因此,
必须将Designer中Dialog的ObjectName设置为相应的类名,才能在自动编译过程中正确衔接两个文件。
还值得一提的是,在aboutdialog.h中的namaspace声明也是可以去掉,如果声明出错也会导致冲突问题;
#ifndef ABOUTDIALOG_H #define ABOUTDIALOG_H #include <QDialog> #include "ui_aboutdialog.h" //新添项 /* 以下内容被新添项替换 namespace Ui { class AboutDialog; } */ class AboutDialog : public QDialog { Q_OBJECT public: AboutDialog(QWidget *parent = 0); ~AboutDialog(); private: Ui::AboutDialog *ui; }; #endif // ABOUTDIALOG_H
多么奇妙的问题,多么狗血的解决方式。花了我一天的时间才搞懂,而每次搞懂这些问题,对于这些知识就理解的更加透彻,这又是多么狗血的学习模式啊!!!