http://blog.csdn.net/woshixingaaa/archive/2010/07/05/5714863.aspx
用最新的 QtCreator 选择 GUI 的应用会产生含有如下文件的工程
下面就简单分析下各部分的功能。
.pro 文件是供 qmake 使用的文件,不是本文的重点【不过其实也很简单的】,在此不多赘述。
所以呢,还是从 main 开始,
- #include <QtGui/QApplication>
- #include "mainwindow.h"
- int main( int argc, char *argv[])
- {
- QApplication a(argc, argv);
- MainWindow w;
- w.show();
- return a.exec();
- }
- #include
- <QtGui/QApplication>
- #include "mainwindow.h"
- int main( int argc, char *argv[])
- {
- QApplication a(argc, argv);
- MainWindow w;
- w.show();
- return a.exec();
- }
很简单 的样子
QApplication a(argc, argv) 和a.exec() 可以理解为载入了Qt 的架构,跑Qt 的程序都要有此部,就不多说了。
其中调用了个MainWindow 并 把它show 了出来,具体分析下
下面是mainwindow.h 中 的内容
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QtGui/QMainWindow>
- namespace Ui
- {
- class MainWindow;
- }
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public :
- MainWindow(QWidget *parent = 0);
- ~MainWindow();
- private :
- Ui::MainWindow *ui;
- };
- #endif // MAINWINDOW_H
- #ifndef
- MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QtGui/QMainWindow>
- namespace Ui
- {
- class MainWindow;
- }
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public :
- MainWindow(QWidget *parent = 0);
- ~MainWindow();
- private :
- Ui::MainWindow *ui;
- };
- #endif // MAINWINDOW_H
开始的namespace Ui 可能让人有点摸不着头脑,这是因为qt 把ui 相关的类单独独立了出来,但类名相同,禁用namespace 区 别【但是就目前的使用来说,感觉这样做不怎么好,后面我会解释原因】
声 明namespace Ui 是因为要调用Ui 中 的MainWindow ,此MainWindow 非 彼MainWindow ,后面涉及的*ui 指 针会调用它!
关于Q_OBJECT 就不说了,Qt 中与signal 和slot 相关的类都要这么声明下。
仔细看出了构造,析构就没啥了,只 有那么个*ui !不过现在如果运行下,也只会生成个窗体而已。
下面来看构造函数和析构函数,其实 也就是mainwindow.c
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent), ui(new Ui::MainWindow)
- {
- ui->setupUi(this );
- }
- MainWindow::~MainWindow()
- {
- delete ui;
- }
- #include
- "mainwindow.h"
- #include "ui_mainwindow.h"
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent), ui(new Ui::MainWindow)
- {
- ui->setupUi(this );
- }
- MainWindow::~MainWindow()
- {
- delete ui;
- }
构 造 时 在堆 上new 了个Ui 域中的MainWindow ,并调用setupUi ,析构仅仅 是将其delete 了,还是很简单!
正如前面所述Qt 很好的把ui 分离了出去,前面图中的那个.ui 文件就是让QtDesigner 使的布局用文 件!
现在运行下,会生成ui_mainwindow.h ,这个里面会涉及到真正布局用的函数,也就是那个Ui 域中的MainWindow. 下面具体看一下,
- #ifndef UI_MAINWINDOW_H
- #define UI_MAINWINDOW_H
- #include <QtCore/QVariant>
- #include <QtGui/QAction>
- #include <QtGui/QApplication>
- #include <QtGui/QButtonGroup>
- #include <QtGui/QHeaderView>
- #include <QtGui/QMainWindow>
- #include <QtGui/QMenuBar>
- #include <QtGui/QStatusBar>
- #include <QtGui/QToolBar>
- #include <QtGui/QWidget>
- QT_BEGIN_NAMESPACE
- class Ui_MainWindow
- {
- public :
- QMenuBar *menuBar;
- QToolBar *mainToolBar;
- QWidget *centralWidget;
- QStatusBar *statusBar;
- void setupUi(QMainWindow *MainWindow)
- {
- if (MainWindow->objectName().isEmpty())
- MainWindow->setObjectName(QString::fromUtf8("MainWindow" ));
- MainWindow->resize(600, 400);
- menuBar = new QMenuBar(MainWindow);
- menuBar->setObjectName(QString::fromUtf8("menuBar" ));
- MainWindow->setMenuBar(menuBar);
- mainToolBar = new QToolBar(MainWindow);
- mainToolBar->setObjectName(QString::fromUtf8("mainToolBar" ));
- MainWindow->addToolBar(mainToolBar);
- centralWidget = new QWidget(MainWindow);
- centralWidget->setObjectName(QString::fromUtf8("centralWidget" ));
- MainWindow->setCentralWidget(centralWidget);
- statusBar = new QStatusBar(MainWindow);
- statusBar->setObjectName(QString::fromUtf8("statusBar" ));
- MainWindow->setStatusBar(statusBar);
- retranslateUi(MainWindow);
- QMetaObject::connectSlotsByName(MainWindow);
- } // setupUi
- void retranslateUi(QMainWindow *MainWindow)
- {
- MainWindow->setWindowTitle(QApplication::translate("MainWindow" , "MainWindow" , 0, QApplication::UnicodeUTF8));
- Q_UNUSED(MainWindow);
- } // retranslateUi
- };
- namespace Ui {
- class MainWindow: public Ui_MainWindow {};
- } // namespace Ui
- QT_END_NAMESPACE
- #endif // UI_MAINWINDOW_H
- #ifndef
- UI_MAINWINDOW_H
- #define UI_MAINWINDOW_H
- #include <QtCore/QVariant>
- #include <QtGui/QAction>
- #include <QtGui/QApplication>
- #include <QtGui/QButtonGroup>
- #include <QtGui/QHeaderView>
- #include <QtGui/QMainWindow>
- #include <QtGui/QMenuBar>
- #include <QtGui/QStatusBar>
- #include <QtGui/QToolBar>
- #include <QtGui/QWidget>
- QT_BEGIN_NAMESPACE
- class Ui_MainWindow
- {
- public :
- QMenuBar *menuBar;
- QToolBar *mainToolBar;
- QWidget *centralWidget;
- QStatusBar *statusBar;
- void setupUi(QMainWindow *MainWindow)
- {
- if (MainWindow->objectName().isEmpty())
- MainWindow->setObjectName(QString::fromUtf8("MainWindow" ));
- MainWindow->resize(600, 400);
- menuBar = new QMenuBar(MainWindow);
- menuBar->setObjectName(QString::fromUtf8("menuBar" ));
- MainWindow->setMenuBar(menuBar);
- mainToolBar = new QToolBar(MainWindow);
- mainToolBar->setObjectName(QString::fromUtf8("mainToolBar" ));
- MainWindow->addToolBar(mainToolBar);
- centralWidget = new QWidget(MainWindow);
- centralWidget->setObjectName(QString::fromUtf8("centralWidget" ));
- MainWindow->setCentralWidget(centralWidget);
- statusBar = new QStatusBar(MainWindow);
- statusBar->setObjectName(QString::fromUtf8("statusBar" ));
- MainWindow->setStatusBar(statusBar);
- retranslateUi(MainWindow);
- QMetaObject::connectSlotsByName(MainWindow);
- } // setupUi
- void retranslateUi(QMainWindow *MainWindow)
- {
- MainWindow->setWindowTitle(QApplication::translate("MainWindow" ,
- "MainWindow" , 0, QApplication::UnicodeUTF8));
- Q_UNUSED(MainWindow);
- } // retranslateUi
- };
- namespace Ui {
- class MainWindow: public Ui_MainWindow {};
- } // namespace Ui
- QT_END_NAMESPACE
- #endif // UI_MAINWINDOW_H
吼吼,一下子多了不少, 但其实还是很容易的。Ui_MainWindow 声明了几个构件,具体我就不说了,因为也没啥可说 的,它实现了setupUi 函式,也就是前面那个MainWindow 中 调用的setupUi 。
但是要说明的是QMetaObject::connectSlotsByName 函 式会自动连接相应名称的信号与槽,但要注意它连接的是传入的MainWindow 及其子构件【不是 子类】,注意前边 ui->setupUi(this) 中传入的 this ,也就是非 ui 域中的 MainWindow ,所以如果要声明 signal 和 slot 时还是要在非 ui 域的 MainWindow 中来声明,然后通过 ui->xxx 的形式来与 GUI 产生交互!如果我们在 QtDesiner 中拖放一个按钮然后点击 go to slot 就很容易印证这一点。
retranslateUi 则会为ui 中的构件命名,具体也不在此多说。
最后还是看看这段代码
namespace Ui {
class MainWindow: public Ui_MainWindow {};
} // namespace Ui
前面非Ui 域中的MainWindow 的*ui 指向的是Ui 域中的MainWindow ,而Ui 域中的MainWindow 出了继承了Ui_MainWindow 之 外,内部一贫如洗!【有点绕口了】
来张图 片,再复习下
最后要说明的有两点,个人感觉是QtCreator 的BUG ,
其一是如果自己定制控件,并且想在内置的designer 中载入,win 下用mingw 是不可行的,因为sdk 套件中的designer 是用微软的编译器编译的,当然也有个比较方便的解决的办法,就是把qtcreator 的源码下来,用现有的creator 再 编译一遍,然后覆盖过去就行了。
其二也是前面提到的,两个同名的MainWindow 仅用Ui 域来区分,虽然感觉这样做 从设计上来说是很美的,但调试时却会有些许的问题,总之在creator 中调试不能识别正确的域, 具体见下图例
像上面这张图this 实 际上应该指向的是非 Ui 域中的MainWindow 【this 其实 指向的是MainWindow ,它并不知是哪个域的MainWindow , 再往下展开就错误的指向了Ui 域 】,但调试的数据区指向了Ui 域中的MainWindow ,当然也不是没有解决的 办法,你可以手工将Ui 域中的MainWindow 改 下名就可以获得正确的调试信息了,只是这样做稍显麻烦,而且再度运行qmake 后可能还要重新修 改。