文章目錄
- Reacting to Language Changes
使用Qt有一些時間了,一直在IDE環境(qtcreator和VS2003+整合器)中使用,自然少了很多麻煩的步驟。但是在享受這種便利的同時,我們也失去了理解更多知識背後的點滴。在IDE中,如果我們要開發一個對話方塊,通常是使用 “建立—>Qt—>Qt設計師介面類” 這樣IDE會自動的幫我們產生三個檔案(filename.ui, filename.h,filename.cpp)。qmake也非常智能,可以自動檢測到這個使用者介面檔案(filename.ui)並且生產適當的makefile規則。這樣在編譯之前,IDE會自動調用uic(Qt內建的使用者介面編譯器,User
Interface Compiler)將介面檔案(filename.ui)轉換成C++代碼並儲存在ui_filename.h檔案中。並且在另外兩個C++源檔案(filename.h和filename.cpp)中使用了組合(即委託或代理)的方式使用了ui_filename.h裡的類(該類通常定義在命名空間Ui下)。
如果你不主動的留心這些細節,你可能永遠都不明白這些,即使使用了多年的Qt,我就是這樣。一次,項目組的需求人員嫌棄我們開發人員做的介面布局不夠恰當,美觀。於是有了自己來開發介面的想法。很好!開發人員很快手把手的教會了需求人員用Qt Designer設計表單介面,然而,等到需求人員把 pureui_filename.ui檔案扔給我們開發人員使用時,我們頓時傻了眼,怎麼用?於是使用了一個最愚蠢當然也是最簡單的辦法: 還是和之前一樣,通過IDE“建立—>Qt—>Qt設計師介面類”產生與“pureui_filename.”同名的檔案,然後用需求人員給的pureui_filename.ui替換IDE自動產生的
*.ui 檔案。雖然轉了一個小彎,但目的達到!
後來想想,總覺得多少有些遺憾,於是查閱了Qt文檔之Using a Designer UI File in Your Application
在這個文檔中,詳細說明了在應用程式中使用UI檔案的方法。
一、直接的方法(The Direct Approach)
即把filename.ui經過uic轉換後的C++代碼檔案ui_filename.h直接包含,使用其裡面Ui命名空間下的類(名稱和主表單的objectname相同,這裡假設為GoToCellDialog)。
#include "ui_gotocelldialog.h" // uic工具將gotocelldialog.ui產生的C++代碼 int main(int argc, char *argv[]) { QApplication app(argc, argv); QDialog *dialog= new QDialog; // 用於顯示介面的父表單QDialog(QWidget的子類) Ui::GotoCellDialog ui; // 介面類,必須顯示在一個QWidget(或其子類)上 ui.setupUi(dialog); // 將QDialog設定為 GotoCellDialog 的父表單,這樣GotoCellDialog 裡面定義的控制項就會顯示在QDialog表單內 dialog->show(); return app.exec(); }
二、單繼承方式(The Single Inheritance Approach)
單繼承方式是相對於後面要講的多繼承方式,單繼承方式也稱組合(即委託或代理)方式。單繼承方式簡單來說就是在代碼中首先要自訂一個子類(例如下文中的GoToCellDialog類),該類要從form對應的表單類(或其相容的子類)派生;並用ui產生的類定義一個類裡的成員變數,該成員變數可以是值也可以是指標,根據使用成員變數的形式不同,又分為成員變數和指標成員變數兩種形式。這樣在GoToCellDialog的建構函式中可以直接調用ui和ui中的變數和函數,使用起來很方便。
1、使用成員變數
即將 Ui::GotoCellDialog ui; 作為類GotoCellDialog(只繼承自QDialog,單一繼承)的成員變數。這裡有一點值得注意的地方,就是ui檔案提供的類被包含在了名為Ui的name space裡,這樣做的目的是將ui檔案的命名空間與使用者的代碼分離,避免兩者出現命名衝突的情況。
標頭檔: gotocelldialog.h
#include <QDialog>#include "ui_gotocelldialog.h" // 因為是成員變數形式,必須包含相應的標頭檔 class GoToCellDialog: public QDialog { Q_OBJECT public: explicit GoToCellDialog(QDialog *parent = 0); private slots: void on_lineEdit_textChanged(); private: Ui::GoToCellDialog ui; };
實現檔案: gotocelldialog.cpp
#include "gotocelldialog.h"#include <QtGui>GoToCellDialog::GoToCellDialog(QWidget *parent) : QDialog(parent){ ui.setupUi(this); QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}"); lineEdit->setValidator(new QRegExpValidator(regExp, this)); connect(okButton, SIGNAL(clicked()), SLOT(accept())); connect(cancelButton, SIGNAL(clicked()), SLOT(reject()));}void GoToCellDialog::on_lineEdit_textChanged(){ // boolhasAcceptableInput () const // This property holds whether the input satisfies the inputMask and the validator. // By default, this property is true. okButton->setEnabled(lineEdit->hasAcceptableInput());}
2、使用指標成員變數
與成員變數形式相似,唯一不同的是,將Ui::GoToCellDialog聲明為指標成員,即 Ui::GoToCellDialog *ui;
因此,相應的標頭檔中只要前置聲明即可:
namespace Ui { class GoToCellDialog; } // 前置聲明即可,只在實現檔案中包含相應的標頭檔 class GoToCellDialog: public QDialog{ // 同上 private: Ui::GoToCellDialog *ui; };
實現檔案:
#include "ui_gotocelldialog.h" GoToCellDialog::GoToCellDialog(QDialog *parent) : QDialog(parent), ui(new Ui::GoToCellDialog) { ui->setupUi(this); } CalculatorForm::~CalculatorForm() { delete ui; // 切記刪除,釋放資源 }
三、多繼承方式(The Multiple Inheritance Approach)
多繼承方式就是自訂的類從表單類和Ui類多重派生。看代碼就清楚了:
標頭檔:
#ifndef GOTOCELLDIALOG_H#define GOTOCELLDIALOG_H#include <QDialog>#include "ui_gotocelldialog.h"class GoToCellDialog : public QDialog, public Ui::GoToCellDialog{ Q_OBJECTpublic: explicit GoToCellDialog(QWidget *parent = 0);private slots: void on_lineEdit_textChanged();};#endif // GOTOCELLDIALOG_H
實現檔案:
#include "gotocelldialog.h"#include <QtGui>GoToCellDialog::GoToCellDialog(QWidget *parent) : QDialog(parent){ this->setupUi(this); //第1個this指Ui::GoToCellDialog,第2個this指(QDialog) 即 Ui::GoToCellDialog->setupUi(QDialog) QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}"); lineEdit->setValidator(new QRegExpValidator(regExp, this)); connect(okButton, SIGNAL(clicked()), SLOT(accept())); connect(cancelButton, SIGNAL(clicked()), SLOT(reject()));}void GoToCellDialog::on_lineEdit_textChanged(){ // boolhasAcceptableInput () const // This property holds whether the input satisfies the inputMask and the validator. // By default, this property is true. okButton->setEnabled(lineEdit->hasAcceptableInput());}
PS:關於UI介面中的國際化
如果使用者介面語言發送了改變,Qt通過發送 QEvent::LanguageChange 事件通知應用程式。為了調用 retranslateUi() 函數以達到切換語言的目的,我們需要重新實現介面類裡面的QWidget::changeEvent() 事件處理函數。
Reacting to Language Changes
Qt notifies applications if the user interface language changes by sending an event of the type QEvent::LanguageChange. To call the member
function retranslateUi() of the user interface object, we reimplement QWidget::changeEvent() in the form class, as follows:
void CalculatorForm::changeEvent(QEvent *e) { QWidget::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } }