Qt - Designer設計師的使用


Designer設計師的使用

在前面的課程中中,我們學習了怎么樣用代碼來把Qt的界面寫出來,代碼控制界面,控制力確實比較好,但是免不了復雜的代碼,而且需要豐富的想象力。

很多時候運行時的樣子,並不是我們想要的,所以說我們可以用Qt給我們提供的Qt Designer(界面設計師),拖拖拽拽就可以直觀的創建出程序大體的界面。

1.1 創建帶UI文件的項目

  • 雙擊.ui文件打開設計師界面

  • 設計師面板介紹

    • 組件面板:窗口左側是界面設計組件面板,分為多個組,如Layouts、Buttons、Display Widgets等,界面設計的常見組件都可以在組件面板里找到。

    • 中間主要區域是待設計的窗體。如果要將某個組件放置到窗體上時,從組件面板上拖放一個組件到窗體上即可。例如,先放一個 Label 和一個 Push Button 到窗體上。

    • Signals 和 Slots 編輯器與 Action 編輯器是位於待設計窗體下方的兩個編輯器。Signals 和Slots 編輯器用於可視化地進行信號與槽的關聯,Action 編輯器用於可視化設計 Action。

    • 布局和界面設計工具欄:窗口上方的一個工具欄,工具欄上的按鈕主要實現布局和界面設計。

    • 對象瀏覽器(Object Inspector):窗口右上方是 Object Inspector,用樹狀視圖顯示窗體上各組件之間的布局包含關系,視圖有兩列,顯示每個組件的對象名稱(ObjectName)和類名稱。

    • 屬性編輯器(Property Editor):窗口右下方是屬性編輯器,是界面設計時最常用到的編輯器。屬性編輯器顯示某個選中的組件或窗體的各種屬性及其取值,可以在屬性編輯器里修改這些屬性的值。

1.2 UI設計器使用

1,轉到槽

  • 遞歸搜索給定對象的所有子對象,並將來自它們的匹配信號連接到遵循以下形式的對象槽:

    void on_<object name>_<signal name>(<signal parameters>);

    讓我們假設我們的對象有一個 QPushButton 類型的子對象,對象名為 button1。 捕捉按鈕的 clicked() 信號的插槽是:

       void on_button1_clicked();

    如果對象本身具有正確設置的對象名稱,則其自身的信號也連接到其各自的插槽。

2,自定義控件(提升為)

 

 

1.3 UI設計師原理

就算我們不編寫一行程序語句,都能實現界面功能,Qt 是怎么實現的呢?

為了搞清楚Widget類的定義,以及界面功能的實現原理,先將項目進行編譯。編譯后在項目目錄下會自動生成一個文件 ui_widget.h,這樣對於一個窗口,就有 4 個文件了,各文件的功能說明見下表。

文件名 描述
widget.h 定義Widget類的頭文件
widget.cpp Widget 類的功能實現源文件
widget.ui 界面文件,由UI設計器自動生成,存儲了窗體上各個組件的屬性設置和布局
ui_widget.h 編譯后,根據窗體上的組件及其屬性、信號與槽的關聯等自動生成的一個類的定義文件,類的名稱是Ui_Widget

下面分別分析各個文件的內容及其功能,以及它們是如何聯系在一起工作,實現界面的創建與顯示的。

Widget.h

#ifndef WIDGET_H
#define WIDGET_H
​
#include <QWidget>
​
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
​
class Widget : public QWidget
{
    Q_OBJECT
​
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
​
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H
  • namespace申明

    代碼中有如下的一個 namespace 聲明:

    namespace Ui { class Widget; }

    這是聲明了一個名為 Ui 的命名空間(namespace),包含一個類 Widget。但是這個類 Widget 並不是本文件里定義的類 Widget,而是 ui_widget.h 文件里定義的類,用於描述界面組件的。這個聲明相當於一個外部類型聲明(具體要看完 ui_widget.h 文件內的解釋之后才能搞明白)。

  • private指針定義

    Ui::Widget *ui;

    這個指針是用前面聲明的 namespace Ui 里的 Widget 類定義的,所以指針 ui 是指向可視化設計的界面,后面會看到要訪問界面上的組件,都需要通過這個指針 ui。

 

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 對應的類定義文件。

  • 在構造函數初始化參數列表里有這么一段代碼

    ui(new Ui::Widget)

    其意義是:執行父類 QWidget 的構造函數,創建一個 Ui::Widget 類的對象 ui。這個 ui 就是 Widget 的 private 部分定義的指針變量 ui。

  • 構造函數里只有一行代碼

    ui->setupUi(this);

    它是執行了 Ui::Widget 類的 setupUi() 函數,這個函數實現窗口的生成與各種屬性的設置、信號與槽的關聯(后面會具體介紹)。

  • 析構函數只是簡單地delete用 new 創建的指針 ui。

  • 所以,在 ui_widget.h 文件里有一個 namespace 名稱為 Ui,里面有一個類 Widget 是用於描述可視化設計的窗體,且與 widget.h 里定義的類同名。在 Widget 類里訪問 Ui::Widget 類的成員變量或函數需要通過 Widget 類里的 ui 指針,如同構造函數里執行 ui->setupUi( this) 函數那樣。

Widget.ui

widget.ui 是界面定義文件,是一個 XML 文件,定義了窗口上的所有組件的屬性設置、布局,及其信號與槽函數的關聯等。用UI設計器可視化設計的界面都由 Qt 自動解析,並以 XML 文件的形式保存下來。在設計界面時,只需在 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>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Widget</string>
  </property>
 </widget>
 <resources/>
 <connections/>
</ui>

 

ui_Widget.h

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 也沒有必要添加到項目里。

#ifndef UI_WIDGET_H
#define UI_WIDGET_H
​
#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QWidget>
​
QT_BEGIN_NAMESPACE
​
class Ui_Widget
{
public:
​
    void setupUi(QWidget *Widget)
    {
        if (Widget->objectName().isEmpty())
            Widget->setObjectName(QString::fromUtf8("Widget"));
        Widget->resize(800, 600);
​
        retranslateUi(Widget);
​
        QMetaObject::connectSlotsByName(Widget);
    } // setupUi
​
    void retranslateUi(QWidget *Widget)
    {
        Widget->setWindowTitle(QCoreApplication::translate("Widget", "Widget", 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;
    • 定義了 setupUi() 函數,這個函數用於創建各個界面組件,並設置其位置、大小、文字內容、字體等屬性,設置信號與槽的關聯。setupUi() 函數體的第一部分是根據可視化設計的界面內容,用 C++ 代碼創建界面上各組件,並設置其屬性。

      接下來,setupUi() 調用了函數 retranslateUi(Widget),用來設置界面各組件的文字內容屬性,如標簽的文字、按鍵的文字、窗體的標題等。將界面上的文字設置的內容獨立出來作為一個函數 retranslateUi(),在設計多語言界面時會用到這個函數。

      setupUi() 函數的第三部分是設置信號與槽的關聯:

      QMetaObject::connectSlotsByName(Widget);

      該代碼是設置槽函數的關聯方式,用於將 UI 設計器自動生成的組件信號的槽函數與組件信號相關聯。

      所以,在Widget 的構造函數里調用 ui->setupUI(this),就實現了窗體上組件的創建、屬性設置、信號與槽的關聯。

    • 定義 namespace Ui,並定義一個從Ui_Widget 繼承的類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 指針可以訪問可視化設計的界面組件就可以了

 

1.4 用Ui文件生成頭文件

  • 1,打開終端,並切換工作目錄到.ui文件所在的目錄

  • 2,輸入如下命令,可以看到ui_widget.h文件就生成出來了

    uic widget.ui -o ui_widget.h

1.5 使用ui_widget.h

一句話,要讓ui designer設計出來的界面顯示出來,只要能設法調用Ui_widget類的setupUi函數就行了。

三步即可完成

  • 1,前置聲明

    //widget.h
    namespace Ui 
    {
        class widget;
    }
  • 2,類中定義

    //widget.h
    private:
        Ui::widget* ui;
  • 3,申請內存,設置ui

    //widget.cpp
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        ,ui(new Ui::widget) //給ui指針分配內存
    {
            ui->setupUi(this);  //給當前窗口this,設置ui界面
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM