當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > 如何使用Qt Designer生成的ui文件
進行Qt應(yīng)用程序開發(fā)時,經(jīng)常利用Qt Designer來進行圖形用戶界面的設(shè)計工作。利用它進行圖形界面的設(shè)計工作有著直觀、方面、易于后期維護的優(yōu)點。在Qt Designer里面做的所有工作,終會保存為一個XML格式的ui文件,該文件保存了很多窗口部件、布局等的位置和狀態(tài)信息。而當(dāng)我們開發(fā)一個應(yīng)用程序時面臨的問題便是我們?nèi)绾问褂眠@個ui文件。對此Qt提供了一個用戶界面編譯器,該工具可以從這個XML格式的ui文件生成一個C++格式的.h頭文件。命令的使用方法是
uic -o 輸出文件名(.h文件) 源文件名(.ui文件)
習(xí)慣上生成的.h文件名為在源文件名的前面加上ui_前綴,例如源文件名為calculatorform.ui,則生成的.h文件名為ui_calculatorform.h,使用的命令如下:
uic -o ui_calculatorform.h calculatorform.ui
生成的頭文件中定義了兩個類,其中一個的主要內(nèi)容如下:
●指向各種widgets,layouts,layout items, button groups以及actions的指針
● 一個稱為setupUi()的成員函數(shù)用來在構(gòu)建各種窗口部件和布局,完成初始化及信號/槽的連接
●一個稱為translateUi()的成員函數(shù)來處理文本翻譯相關(guān)的工作。
另一個類從該類簡單的公有繼承,只不過放在了一個叫Ui的命令空間中 ,例如:
class Ui_Calculatorform
{
public:
QPushButton *pushButton;
...
void setupUi(QWidget *Widget)
{ ... } // setupUi
void retranslateUi(QWidget *Widget)
{ ... } // retranslateUi
};
namespace Ui {
class Calculatorform: public Ui_Calculatorform {};
} // namespace Ui
如何使用該類就是我們接下來要討論的主題。
有三種主要的方式
方法一:直接法
直接法需要在main.cpp中包含剛才uic所生成的.h頭文件。然后在main函數(shù)中我們創(chuàng)建一個QWidget的對象及一個該用戶界面類的對象,并調(diào)用類的setupUi成員函數(shù)來使我們的QWidgt對象成為該界面對象的持有者
例如:
#include "ui_calculatorform.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget *widget = new QWidget; //創(chuàng)建一個QWidget對象
Ui::CalculatorForm ui; //創(chuàng)建一個該界面類的對象
ui.setupUi(widget); //讓我們的QWidget對象成為該界面對象的placeholder
widget->show();
return app.exec();
}
Ui::CalculatorForm是ui_calculatorform.h中生成的類。
直接法簡單易用,但是實際中很少應(yīng)用這種方法。因為我們通常需要Designer中產(chǎn)生的部件之間有互動,且和應(yīng)用程序的其余代碼良好集成。然而這種方法不利于擴展。
方法二:單繼承法
這種方法要求我們從標(biāo)準(zhǔn)的窗口部件(例如QWidget或QDialog等)去繼承得到一個子類。而在該子類中,包含一個私有的用戶界面類對象。包含的方式又分為兩種:
一是直接包含一個該類的對象來作為成員變量,例如:
#include "ui_calculatorform.h"
class CalculatorForm : public QWidget
{
Q_OBJECT
public:
CalculatorForm(QWidget *parent = 0);
...
private:
Ui::CalculatorForm ui; //直接包含一個該類的對象來作為成員變量
};
對應(yīng)的實現(xiàn)文件需要構(gòu)造函數(shù)中完成初始化,例如:
CalculatorForm::CalculatorForm(QWidget *parent) : QWidget(parent)
{
ui.setupUi(this);
}
二是包含一個指向該界面類對象的指針來作為成員變量,例如:
namespace Ui {
class CalculatorForm;
}
class CalculatorForm : public QWidget
...
virtual ~CalculatorForm();
...
private:
Ui::CalculatorForm *ui; //包含一個指向該界面類對象的指針來作為成員變量
...
由于頭文件中只需用到指針,所以不需要完整的類定義,可以加快編譯的速度。
對應(yīng)的實現(xiàn)文件,應(yīng)該像下面這樣來做
#include "ui_calculatorform.h"
CalculatorForm::CalculatorForm(QWidget *parent) :
QWidget(parent), ui(new Ui::CalculatorForm)
{
ui->setupUi(this);
}
CalculatorForm::~CalculatorForm()
{
delete ui;
}
這種方法是目前Qt官方推薦的主要方法。
方法三:多繼承法
同時從標(biāo)準(zhǔn)的窗口部件基類(如QWidget)和uic生成的.h文件中的用戶界面類(如Ui::CalculatorForm)做多繼承,得到一個子類。這種方法允許直接在子類中訪問預(yù)先定義好的窗口部件,而不需要加ui之類的前綴。例如:
#include "ui_calculatorform.h"
class CalculatorForm : public QWidget, private Ui::CalculatorForm
{
Q_OBJECT
public:
CalculatorForm(QWidget *parent = 0);
private slots:
... //由于從Ui::CalculatorForm直接繼承,所以可以直接用其中的窗口部件成員
};
這種方法因為用到了多繼承而顯得略為復(fù)雜,以前的Qt版本中常采用此法,現(xiàn)在Qt Creator默認的已不使用這種方法了。