用最新的QtCreator選擇GUI的應用會產(chǎn)生含有如下文件的工程
下面就簡單分析下各部分的功能。
.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();
- }
很簡單的樣子
QApplication a(argc, argv)和a.exec()可以理解為載入了Qt的架構,跑Qt的程序都要有此部,就不多說了。
其中調用了個MainWindow并把它show了出來,具體分析下
下面是mainwindow.h中的內(nèi)容
- #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區(qū)別【但是就目前的使用來說,感覺這樣做不怎么好,后面我會解釋原因】
聲明namespace Ui是因為要調用Ui中的MainWindow,此MainWindow非彼MainWindow,后面涉及的*ui指針會調用它!
關于Q_OBJECT就不說了,Qt中與signal和slot相關的類都要這么聲明下。
仔細看出了構造,析構就沒啥了,只有那么個*ui!不過現(xiàn)在如果運行下,也只會生成個窗體而已。
下面來看構造函數(shù)和析構函數(shù),其實也就是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;
- }
構造時在堆上new了個Ui域中的MainWindow,并調用setupUi,析構僅僅是將其delete了,還是很簡單!
正如前面所述Qt很好的把ui分離了出去,前面圖中的那個.ui文件就是讓QtDesigner使的布局用文件!
現(xiàn)在運行下,會生成ui_mainwindow.h,這個里面會涉及到真正布局用的函數(shù),也就是那個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);
- }
- void retranslateUi(QMainWindow *MainWindow)
- {
- MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0, QApplication::UnicodeUTF8));
- Q_UNUSED(MainWindow);
- }
- };
- namespace Ui {
- class MainWindow: public Ui_MainWindow {};
- }
- QT_END_NAMESPACE
- #endif // UI_MAINWINDOW_H
吼吼,一下子多了不少,但其實還是很容易的。Ui_MainWindow聲明了幾個構件,具體我就不說了,因為也沒啥可說的,它實現(xiàn)了setupUi函式,也就是前面那個MainWindow中調用的setupUi。
但是要說明的是QMetaObject::connectSlotsByName函式會自動連接相應名稱的信號與槽,但要注意它連接的是傳入的MainWindow及其子構件【不是子類】,注意前邊ui->setupUi(this)中傳入的this,也就是非ui域中的MainWindow,所以如果要聲明signal和slot時還是要在非ui域的MainWindow中來聲明,然后通過ui->xxx的形式來與GUI產(chǎn)生交互!如果我們在QtDesiner中拖放一個按鈕然后點擊go
to slot就很容易印證這一點。
retranslateUi則會為ui中的構件命名,具體也不在此多說。
最后還是看看這段代碼
- namespace Ui {
-
- class MainWindow: public Ui_MainWindow {};
-
- }
前面非Ui域中的MainWindow的*ui指向的是Ui域中的MainWindow,而Ui域中的MainWindow出了繼承了Ui_MainWindow之外,內(nèi)部一貧如洗!【有點繞口了】
來張圖片,再復習下
最后要說明的有兩點,個人感覺是QtCreator的BUG,
其一是如果自己定制控件,并且想在內(nèi)置的designer中載入,win下用mingw是不可行的,因為sdk套件中的designer是用微軟的編譯器編譯的,當然也有個比較方便的解決的辦法,就是把qtcreator的源碼下來,用現(xiàn)有的creator再編譯一遍,然后覆蓋過去就行了。
其二也是前面提到的,兩個同名的MainWindow僅用Ui域來區(qū)分,雖然感覺這樣做從設計上來說是很美的,但調試時卻會有些許的問題,總之在creator中調試不能識別正確的域,具體見下圖例
像上面這張圖this實際上應該指向的是非Ui域中的MainWindow【this其實指向的是MainWindow,它并不知是哪個域的MainWindow,再往下展開就錯誤的指向了Ui域】,但調試的數(shù)據(jù)區(qū)指向了Ui域中的MainWindow,當然也不是沒有解決的辦法,你可以手工將Ui域中的MainWindow改下名就可以獲得正確的調試信息了,只是這樣做稍顯麻煩,而且再度運行qmake后可能還要重新修改。