http://c.biancheng.net/view/1820.htmlhtml
Qt 項目中,後綴爲「.ui」的文件是可視化設計的窗體的定義文件,如 widget.ui。雙擊項目文件目錄樹中的文件 widget.ui,會打開一個集成在 Qt Creator 中的 Qt Designer 對窗體進行可視化設計,如圖 1 所示。
瀏覽器
本教程後面將稱這個集成在 Qt Creator 中的 Qt Designer 爲「UI 設計器」,以便與獨立運行的 Qt Designer 區別開來。
圖 1 中的 UI 設計器有如下一些功能區域:編輯器
圖 2 顯示的是選中窗體上放置的標籤組件後屬性編輯器的內容。最上方顯示的文字「LabDemo: QLabel」表示這個組件是一個 QLabel 類的組件,objectName 是LabDemo。函數
屬性編輯器的內容分爲兩列,分別爲屬性的名稱和屬性的值。屬性又分爲多個組,實際上表示了類的繼承關係,如在圖 2 中,能夠看出 QLabel 的繼承關係是QObject→QWidget→QFrame→QLabel
。
objectName 表示組件的對象名稱,界面上的每一個組件都須要一個惟一的對象名稱,以便被引用。界面上的組件的命名應該遵循必定的法則,具體使用什麼樣的命名法則根據我的習慣而定,主要目的是便於區分和記憶,也要便於與普通變量相區分。
設置其餘屬性的值只需在屬性編輯器裏操做便可,如設置 LabDemo 的 text 屬性爲「Hello,World」,只需像圖 2 那樣修改 text 屬性的值便可。工具
提示,標準 C++ 語言裏並無 property 關鍵字,property 是 Qt 對標準 C++ 的擴展,使得在 Qt Designer 裏就能夠可視化設置類的數據。佈局
在圖 1 顯示的設計窗體上,放置一個 Label 和一個 Push Button 組件,它們的主要屬性設置見表 3。
字體
ObjectName | 類名稱 | 屬性設置 | 備註 |
---|---|---|---|
LabDemo | QLabel | Text=」Hello, World」 Font.PointSize=20 Font.bold=true |
設置標籤顯示文字和字體 |
btnClose | QPushButton | Text=」Close」 | 設置按鈕的文字 |
編輯完屬性以後,再爲 btnClose 按鈕增長一個功能,就是單擊此按鈕時,關閉窗口,退出程序。使用 Signals 和 Slots 編輯器完成這個功能,如圖 4 所示。ui
在信號與槽編輯器的工具欄上單擊「Add」按鈕,在出現的條目中,Sender 選擇 btnClose,Signal 選擇 clicked(),Receiver 選擇窗體 Widget,Slot 選擇 close()。這樣設置表示當按鈕 btnClose 被單擊時,就執行 Widget 的 close() 函數,實現關閉窗口的功能。
而後對項目進行編譯和運行,能夠出現如圖 5 所示的窗口,單擊「Close」按鈕能夠關閉程序。this
標籤的文字內容和字體被修改了,窗口標題也顯示爲所設置的標題,而咱們並無編寫一行程序語句,Qt 是怎麼實現這些功能的呢?
爲了搞清楚窗體類的定義,以及界面功能的實現原理,這裏將項目進行編譯。編譯後在項目目錄下會自動生成一個文件 ui_widget.h,這樣對於一個窗體,就有 4 個文件了,各文件的功能說明見表 6。
spa
文件名 | 功能 |
---|---|
widget.h | 定義窗體類的頭文件,定義了類Widget |
widget.cpp | Widget 類的功能實現源程序文件 |
widget.ui | 窗體界面文件,由UI設計器自動生成,存儲了窗體上各個組件的屬性設置和佈局 |
ui_widget.h | 編譯後,根據窗體上的組件及其屬性、信號與槽的關聯等自動生成的一個類的定義文件,類的名稱是Ui_Widget |
下面分別分析各個文件的內容及其功能,以及它們是如何聯繫在一塊兒工做,實現界面的建立與顯示的。
widget.h 文件是窗體類的頭文件。在建立項目時,選擇窗體基類是 QWidget,在 widget.h 中定義了一個繼承自 QWidget 的類 Widget。
下面是 widget.h 文件的內容:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; }; #endif // WIDGET_H
widget.h 文件有幾個重要的部分。
代碼中有以下的一個 namespace 聲明:
namespace Ui { class Widget; }
這是聲明瞭一個名稱爲 Ui 的命名空間(namespace),包含一個類 Widget。可是這個類 Widget 並非本文件裏定義的類 Widget,而是 ui_widget.h 文件裏定義的類,用於描述界面組件的。這個聲明至關於一個外部類型聲明(具體要看完 ui_widget.h 文件內的解釋以後才能搞明白)。
widget.h 文件的主體部分是一個繼承於 QWidget 的類 Widget 的定義,也就是本實例的窗體類。
在 Widget 類中使用了宏 Q_OBJECT,這是使用 Qt 的信號與槽(signal 和 slot)機制的類都必須加入的一個宏(信號與槽在後面詳細介紹)。
在 public 部分定義了 Widget 類的構造函數和析構函數。
在 private 部分又定義了一個指針。
Ui::Widget *ui;
這個指針是用前面聲明的 namespace Ui 裏的 Widget 類定義的,因此指針 ui 是指向可視化設計的界面,後面會看到要訪問界面上的組件,都須要經過這個指針 ui。
widget.cpp 文件是類 Widget 的實現代碼,下面是 widget.cpp 文件的內容。
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); } Widget::~Widget() { delete ui; }
注意到,在這個文件的包含文件部分自動加入了以下一行內容:
#include "ui_widget.h"
這個就是 Qt 編譯生成的與 UI 文件 widget.ui 對應的類定義文件。
目前只有構造函數和析構函數。其中構造函數頭部是:
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
其意義是:執行父類 QWidget 的構造函數,建立一個 Ui::Widget 類的對象 ui。這個 ui 就是 Widget 的 private 部分定義的指針變量 ui。
構造函數裏只有一行語句:
ui->setupUi(this)
它是執行了 Ui::Widget 類的 setupUi() 函數,這個函數實現窗口的生成與各類屬性的設置、信號與槽的關聯(後面會具體介紹)。
析構函數只是簡單地刪除用 new 建立的指針 ui。
因此,在 ui_widget.h 文件裏有一個 namespace 名稱爲 Ui,裏面有一個類 Widget 是用於描述可視化設計的窗體,且與 widget.h 裏定義的類同名。在 Widget 類裏訪問 Ui::Widget 類的成員變量或函數須要經過 Widget 類裏的 ui 指針,如同構造函數裏執行 ui->setupUi( this) 函數那樣。
widget.ui 是窗體界面定義文件,是一個 XML 文件,定義了窗口上的全部組件的屬性設置、佈局,及其信號與槽函數的關聯等。用UI設計器可視化設計的界面都由 Qt 自動解析,並以 XML 文件的形式保存下來。在設計界面時,只需在 UI 設計器裏進行可視化設計便可,而不用管 widget.ui 文件是怎麼生成的。
下面是 widget.ui 文件的內容:
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Widget</class> <widget class="QWidget" name="Widget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>336</width> <height>216</height> </rect> </property> <property name="windowTitle"> <string>My First Demo</string> </property> <widget class="QLabel" name="Lablabel"> <property name="geometry"> <rect> <x>100</x> <y>70</y> <width>141</width> <height>61</height> </rect> </property> <property name="font"> <font> <pointsize>12</pointsize> <weight>75</weight> <bold>true</bold> </font> </property> <property name="text"> <string>Hello,World</string> </property> </widget> <widget class="QPushButton" name="btnClose"> <property name="geometry"> <rect> <x>210</x> <y>150</y> <width>75</width> <height>23</height> </rect> </property> <property name="text"> <string>Close</string> </property> </widget> </widget> <layoutdefault spacing="6" margin="11"/> <resources/> <connections> <connection> <sender>btnClose</sender> <signal>clicked()</signal> <receiver>Widget</receiver> <slot>close()</slot> <hints> <hint type="sourcelabel"> <x>247</x> <y>161</y> </hint> <hint type="destinationlabel"> <x>167</x> <y>107</y> </hint> </hints> </connection> </connections> </ui>
ui_widget.h 是在對 widget.ui 文件編譯後生成的一個文件,ui_widget.h 會出如今編譯後的目錄下,或與 widget.ui 同目錄(與項目的 shadow build 編譯設置有關)。
文件 ui_widget.h 並不會出如今 Qt Creator 的項目文件目錄樹裏,固然,能夠手工將 ui_widget.h 添加到項目中。方法是在項目文件目錄樹上,右擊項目名稱節點,在調出的快捷菜單中選擇「Add Existing Files…」,找到並添加 ui_widget.h 文件便可。
注意,ui_widget.h 是對 widget.ui 文件編譯後自動生成的,widget.ui 又是經過 UI 設計器可視化設計生成的。因此,對 ui_widget.h 手工進行修改沒有什麼意義,全部涉及界面的修改都應該直接在UI 設計器裏進行。因此,ui_widget.h 也沒有必要添加到項目裏。
下面是 ui_widget.h 文件的內容:
查看 ui_widget.h 文件的內容,發現它主要作了如下的一些工做:
QLabel *LabDemo;
QPushButton *btnClose;
QObject::connect(btnClose, SIGNAL(clicked()), Widget, SLOT(close()));
QMetaObject::connectSlotsByName(Widget);
namespace Ui {
class Widget: public Ui_Widget {};
}
提示:ui_widget.h 文件裏實現界面功能的類是 Ui_Widget。再定義一個類 Widget 從 Ui_Widget 繼承而來,並定義在 namespace Ui 裏,這樣 Ui:: Widget 與 widget.h 裏的類 Widget 同名,可是用 namespace 區分開來。因此,界面的 Ui:: Widget 類與文件 widget.h 裏定義的 Widget 類其實是兩個類,可是 Qt 的處理讓用戶感受不到 Ui:: Widget 類的存在,只須要知道在 Widget 類裏用 ui 指針能夠訪問可視化設計的界面組件就能夠了。
相關文件推薦:
談.ui文件的用法 | 這是一篇對Qt項目中ui文件用法的軟件,有對.ui文件的詳細介紹 |
Qt之UI文件設計和運行機制 | 這是一篇對Qt項目中各個文件總體介紹的一篇軟文,講的很詳細 |
Qt中.ui文件的使用 | .ui文件有3種使用形式在這篇文章中獲得了很好的闡述 |