Qt入門之UI文件設計與運行機制
QMainWindow 是主窗口類,主窗口具有主菜單欄,工具欄和狀態欄,類似於一般的應用程序的窗口
QWidget是所有具體可視界面類的基類,選擇QWidget 創建的界面對各種界面組件都可以支持
QDialog是對話框類,可建立一個基於對話框的界面
項目文件組成
1.項目組織文件samp2_1.pro,存儲項目設置的文件
#表示加入了 core gui模塊。 core gui是Qt用於GUI設計的類庫模板,如果創建的是控制檯(console)應用程序,就不需要加入 core gui
#Qt類庫以模塊的形式組織各種功能的類,根據項目涉及的需求,在項目中添加適當的類庫模塊支持,例如,如果項目中使用到了設計數據庫操作的類就需要用到sql的模塊,在pro文件中需要增加如下一行
#QT +=sql
QT += core gui
#這是個條件執行語句,表示當QT的版本大於4時,才加入widgets模塊
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
#表示生產的目標可執行文件的名稱,即編譯後的可執行文件是samp2_1.exe
TARGET = samp2_1
#表示項目使用的模板是app,是一般的應用程序
TEMPLATE = app
CONFIG += c++11
#SOURCES 、HEADERS 、FORMS 記錄了項目中包含的源程序文件、頭文件和窗體文件(.ui文件)的名稱。這些文件列表是Qt Creator自動添加到項目管理文件裏面的,用戶不需要手動修改。當從項目添加或刪除一個文件時,項目管理文件的條目會自動修改
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
2.主函數文件main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv); //Qt的標準應用程序類
Widget w; //定義並創建窗口
w.show(); //顯示窗口
return a.exec(); //啓動應用程序的執行,開始應用程序的消息循環和事件處理
}
3.窗體相關文件
將項目編譯,編譯後在項目目錄下會自動生成一個ui_widget.h文件(在編譯後的文件夾裏),這樣,對於一個窗體,就有4個文件了 :
widget.h 定義窗體類的頭文件,定義了類Widget
widget.cpp Widget類的功能實現源程序文件
widget.ui 窗體界面文件,
ui_widget.h 編譯後,根據窗體上的組件及屬性、信號與槽的關聯等自動生成的一個類的定義文件,類的名稱是Ui_Widget
下面分析各個文件的內容及其功能,以及他們是如何聯繫到一起工作,實現界面的創建與顯示的。
3.1 widget.h文件
widget.h文件是窗體類的頭文件。在創建項目時,選擇窗體基類的QWidget,在widget.h中定義一個繼承自QWidget的類的Widget:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget; //聲明瞭一個名稱爲 Ui 的命名空間,包含一個類Widget。但這個Widget類並不是本文件裏定義的類Widget,而是ui_widget.h文件中定義的類,用於描述組件的。這個聲明相當與一個外部聲明(具體看完ui_widget.h文件才能搞明白)
}
class Widget : public QWidget //本實例窗口類Widget的定義
{
Q_OBJECT //使用Qt的信號與槽機制都必須加入的宏
public:
explicit Widget(QWidget *parent = nullptr); //構造函數
~Widget(); //析構函數
private:
Ui::Widget *ui; //這個指針是用前面namespace Ui裏的Widget類定義的,所以指針ui指向可視化設計的界面,要訪問界面上的組件,都需要通過這個ui指針
};
#endif // WIDGET_H
3.2 widget.cpp文件
widget.cpp文件是類Widget的實現代碼:
#include "widget.h"
#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。可參考:https://blog.csdn.net/GouplovXim1314/article/details/104349423
{
ui->setupUi(this); //這個函數實現了窗口的生產與各種屬性的設置、信號與槽的關聯
}
Widget::~Widget()
{
delete ui; //析構函數
}
所以,在 ui_widget.h 文件裏有一個 namespace 名稱爲 Ui,裏面有一個類 Widget 類用於描述可視化的窗體,且與widget.h裏定義的類同名。在Widget類裏訪問 Ui::Widget類的成員變量或函數需要通過Widget類裏的 ui 指針,如果構造函數裏執行 ui->setupUi(this)函數那樣。
3.3 ui_widget.h文件
ui_widget.h文件是在對 widget.ui 文件編譯後生成的一個文件,ui_widget.h會出現在編譯後的目錄下,或與widget.ui同目錄(與項目的 shadow build編譯設置有關)。
文件ui_widget.h並不會出現在 Qt Creator 的項目文件目錄樹裏,可手動添加
/********************************************************************************
** Form generated from reading UI file 'widget.ui'
**
** Created by: Qt User Interface Compiler version 5.9.7
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
#ifndef UI_WIDGET_H
#define UI_WIDGET_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QWidget>
QT_BEGIN_NAMESPACE
class Ui_Widget
{
public:
QLabel *label;
QPushButton *btnClose;
void setupUi(QWidget *Widget)
{
if (Widget->objectName().isEmpty())
Widget->setObjectName(QStringLiteral("Widget"));
Widget->resize(400, 300);
QFont font;
font.setFamily(QStringLiteral("Aharoni"));
font.setPointSize(12);
font.setBold(true);
font.setWeight(75);
Widget->setFont(font);
label = new QLabel(Widget);
label->setObjectName(QStringLiteral("label"));
label->setGeometry(QRect(120, 110, 91, 31));
label->setFont(font);
btnClose = new QPushButton(Widget);
btnClose->setObjectName(QStringLiteral("btnClose"));
btnClose->setGeometry(QRect(240, 210, 75, 23));
retranslateUi(Widget);
QObject::connect(btnClose, SIGNAL(clicked()), Widget, SLOT(close()));
QMetaObject::connectSlotsByName(Widget);
} // setupUi
void retranslateUi(QWidget *Widget)
{
Widget->setWindowTitle(QApplication::translate("Widget", "Widget", Q_NULLPTR));
label->setText(QApplication::translate("Widget", "Hello Word", Q_NULLPTR));
btnClose->setText(QApplication::translate("Widget", "\345\205\263\351\227\255", Q_NULLPTR));
} // retranslateUi
};
namespace Ui {
class Widget: public Ui_Widget {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_WIDGET_H
查看ui_widget.h文件,發現他主要做了一下工作:
(1)定義了一個類Ui_Widget,用於封裝可視化界面的設計
(2)自動生成了界面各個組件的類成員變量定義。在 public 部分爲界面上每個組件定義了一個指針變量,變量的名稱就是設置的objectName。比如,在窗體上放置一個QLabel 和 一個QPushButton並命名後,會自動生成定義是:QLabel *LabDemo; QPushButton *btnClose;
(3)定義了setupUi()函數,這個函數用來創建各個界面組件,並設置其位置、大小、文字內容、字體等屬性,設置信號與槽的關聯。
- setupUi()函數體的第一部分是根據可視化設計界面內容,用C++代碼 創建界面上的個組件,並設置其屬性。
- 接下來,setupUi()調用了函數 retranslateUi(Widget),用來設置界面各組件的文字內容屬性,如標籤的文字、按鍵的文字、窗體的標題等。將界面上的文字內容獨立出來作爲一個函數retranslateUi(),在設計多語言界面時會用到這個函數。
-
setupUi()函數的第三部分是設置信號與槽的關聯,本文件中有以下兩行:
QObject::connect(btnClose, SIGNAL(clicked()), Widget, SLOT(close()));
QMetaObject::connectSlotsByName(Widget);
第一行是調用 connect() 函數,將在UI設計器裏設置的信號與槽的關聯轉換爲語句。
第二行是設置槽函數的關聯方式,用於將UI設計器自動生產的組件信號的槽函數與組件信號關聯
所以:在Widget 的構造函數裏調用 ui->setupUi(this),就實現了窗體上組件的創建、屬性設置、信號與槽的關聯
-
定義 namespace Ui,並定義一個從 Ui_Widget 繼承的類 Widget