久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    [QT_042]Qt學習之控件尺寸調整策略(QSizePolicy)_qt setsizepolicy

     wuxinit_ 2023-10-18 發布于湖北

    本文轉自:《Qt編程指南》        作者:奇先生

    Qt編程指南,Qt新手教程,Qt Programming Guide

    6.5 控件尺寸調整策略


    基于 QWidget 的控件都會繼承 sizePolicy 屬性( QSizePolicy 類型),這個屬性包括兩個大的方面內容:伸展因子 (Stretch Factor)和 伸展策略(Policy),這些都會影響到界面最終的布局顯示。我們本節先大致介紹布局器的工作原理,然后分兩小節講解伸展因子、伸展策略以及 QSizePolicy 類其他內容,并通過 Qt 設計師進行一些控件伸展因子設置的示范,最后是兩個尺寸調整策略設置的示例。
     

    6.5.1 布局器工作原理


    當添加控件到布局器時,布局器的工作原理如下:
    (1)所有的控件初始時,布局器根據控件自己的 QWidget::sizePolicy() 和  QWidget::sizeHint()分配相應的空間給各個控件。sizePolicy() 就是控件的尺寸調整策略,比如 QSizePolicy::Fixed 就是不拉伸,空間就是固定的,而 QSizePolicy::Expanding 就是盡可能占據空間,死勁拉伸。sizeHint() 就是控件本身的建議尺寸,或叫最佳尺寸,這個建議尺寸是 Qt 類庫自己根據需要顯示的內容計算的,所有的控件和窗體都能自己計算建議尺寸。
    (2)如果有控件自己設置了大于零的伸展因子(stretch factors),那么在主界面窗口變大時,新增的空閑區域按照控件的伸展因子比例進行分配。伸展因子的內容在下面 6.5.2 小節專門講解。
    (3)如果有控件的伸展因子設置為 0,那么這個控件會盡量不占用窗口變大后的空閑區域,如果其他控件都不想要空閑區域,伸展因子為 0 的控件才會去嘗試占據窗口變大后的空閑區域。默認情況下,所有控件的伸展因子其實都是 0,這時候布局器會優先拉伸尺寸策略為 QSizePolicy::Expanding 的控件。
    (4)當窗口縮小時,布局器會根據控件的最小尺寸限定控件尺寸下限,控件到達它的最小尺寸后就不會繼續縮小。最小尺寸可以是 minimumSize 指定的最小尺寸,如果沒設置 minimumSize ,那么最小尺寸是 minimumSizeHint 指定的最小建議尺寸,minimumSizeHint 是 Qt 類庫自己計算的,一般不需要程序員設置。(有些特殊情況,如果控件尺寸僅僅由伸展因子 stretch factor 決定,那么就沒有最小尺寸和最小建議尺寸)。
    (5)當窗口變大時,布局器會根據控件的最大尺寸限定控件的尺寸上限,控件達到它的最大尺寸后就不再增長。最大尺寸由控件的 maximumSize 指定。(有些特殊情況,如果控件尺寸僅僅由伸展因子 stretch factor 決定,那么就沒有最大尺寸)。

    上面是 Qt 幫助文檔內容的翻譯和解釋,我們現在稍微歸納一下布局器中影響控件拉伸的因素:
    ① 最小尺寸和最大尺寸,控件尺寸會限定在最小尺寸和最大尺寸之間。
    ② 建議尺寸 QWidget::sizeHint(),這個建議尺寸是后續尺寸調整的基礎,在布局時會先給控件分配建議尺寸的空間。
    ③ 伸展因子(stretch factors),根據伸展因子的比例分配新增的空閑空間給各個控件。
    ④ 尺寸策略 QWidget::sizePolicy(),在上述處理之后,那么再根據各個控件的尺寸調整策略決定控件應該盡可能拉伸還是盡量不拉伸。

    這些規律對水平布局器、垂直布局器、網格布局器都是通用的。比較例外的是表單布局器,表單布局器在垂直方向不拉伸,第一列的標簽也不拉伸,受尺寸調整策略影響的只 有第二列的域在水平方向的拉伸行為。

    在影響界面布局的因素中,最小尺寸和最大尺寸可以直接設置控件的 minimumSize 和 maximumSize 屬性,對應的函數為:

    1. void setMinimumSize(const QSize &)       //最小尺寸

    2. void setMinimumSize(int minw, int minh)  //最小尺寸

    3. void setMaximumSize(const QSize &)       //最大尺寸

    4. void setMaximumSize(int maxw, int maxh)  //最大尺寸

    這些函數和屬性我們在 6.1.1 小節專門介紹過,設置最小尺寸和最大尺寸是沒啥技術含量的,比較簡單,這里不贅述了。
    建議尺寸 QWidget::sizeHint() 通常是 Qt 類庫自己根據需要顯示的內容計算的,并沒有直接的設置函數,只能用 QWidget::sizeHint() 函數獲取建議的尺寸。如果程序員不自己定制新的控件類和布局器類,是不需要操心建議尺寸的。
    影響控件拉伸的四個因素中,頭兩個因素通常都比較簡單不用操心,因此我們本節就主要學習伸展因子和尺寸調整策略。
     

    6.5.2 QSizePolicy 之一:伸展因子


    控件和水平布局器、垂直布局器、網格布局器都可以設置伸展因子。窗口拉伸時,布局器會根據每個控件或子布局器的水平和垂直方向的伸展因子,分配新增的空閑空間。例外的是如果控件設置了 sizePolicy 屬性里的策略為 QSizePolicy::Fixed 固定高度或固定寬度,那就不拉伸控件,只拉伸控件之間的間隙。對于固定寬度或高度的控件,沒什么好討論,因為它們不拉伸。我們下面考慮會拉伸的情形。

    本小節是通過三個 ui 文件示范的,沒有用到新項目。讀者可以從如下網址獲取 ui 文本:
    stretchfactors
    下載 threebuttons.ui、fourbuttons.ui、fourlayouts.ui 三個文件,然后可以用 Qt 設計師或 QtCreator 打開它們,根據下面的示范操作這些界面文件。


    (1)控件本身的水平和垂直伸展因子


    通??丶际菑?QWidget 直接或間接派生的,都可以設置 sizePolicy 屬性,在 Qt 設計師或 QtCreator 設計模式,可以在右下角屬性編輯欄看到選中控件或窗體的 sizePolicy 屬性:

    上圖標出的就是 sizePolicy 屬性,里面分為四個小屬性,"水平策略" 和 "垂直策略" 就是下一小節介紹的伸展策略,"水平伸展" 和 "垂直伸展" 就是本小節的伸展因子。

    以三個按鈕控件為例,如果它們的伸展因子都是 0,那么三個按鈕在水平布局里就是均勻拉伸:

    如果把 "One" 按鈕的 "水平伸展" 設為 1,"Two" 按鈕的 "水平伸展" 設為 2,"Three" 按鈕的 "水平伸展" 設為 3,那么在窗口拉大時,該行三個按鈕的伸展因子之和為 1+2+3 == 6,新的空間就按照 1/6 ,2/6 ,3/6 的比例劃分給這三個按鈕,顯示效果就如下面這樣:

    如果把 "One" 按鈕的 "水平伸展" 設為 2,"Two" 按鈕的 "水平伸展" 設為 4,"Three" 按鈕的 "水平伸展" 設為 0,那么在窗口拉大時,分配規律就是:先計算伸展因子之和 2+4+0 == 6,新的空間按照 2/6 ,4/6,0/6 的比例劃分給這三個按鈕,顯示效果如下:

    因為第三個按鈕的伸展因子是 0,第三個按鈕會保持一個建議尺寸,其他兩個按鈕會根據伸展因子的占比進行拉伸。三個水平伸展因子為 2、4、0,其實也可以直接寫成 1、2、0,兩種是等價的,不管有沒有公約數。

    通過設計師或 QtCreator 設計模式修改伸展因子是很簡單的,如果要通過代碼來修改,那么可以用類似下面的代碼:

    1.     //獲取舊的尺寸策略作為底板,修改需要變動的伸展因子

    2. QSizePolicy sp = ui->pushButton1->sizePolicy();
    3. sp.setHorizontalStretch(2); //水平伸展因子
    4. sp.setVerticalStretch(0); //垂直伸展因子
    5. //把新策略設置給按鈕1
    6. ui->pushButton1->setSizePolicy(sp);

    其他類型的控件代碼也可類似的編寫,先獲取舊的策略,在舊策略基礎上修改我們需要變動的伸展因子。設置水平伸展因子的函數聲明為:

    void QSizePolicy::?setHorizontalStretch(int stretchFactor)

    設置垂直伸展因子的函數聲明為:

    void QSizePolicy::?setVerticalStretch(int stretchFactor)

    注意 stretchFactor 的取值范圍是 0 到 255,負數就當做 0,大于 255 就當做 255,因此設置超出范圍的數也沒意義。一般用個位數 的伸展因子就夠用了,伸展因子沒必要弄太大。

    除了控件自身可以設置伸展因子,布局器也可以為內部直屬的控件或子布局器設置伸展因子。如果布局器和內部直屬的控件都設置了伸展因子,那么布局器的設置會覆蓋直屬控件的伸展因子。因此不建議直接設置控件自己的伸展因子屬性,而是通過布局器來設置各個子控件或子布局器的伸展因子。
    另外,從設計上看,控件只能管自己的局部矩形,控件不知道自己的伸展因子會對相鄰控件造成多大影響,控件自身沒有宏觀的概念。尤其是網格布局器,某一行某一列的控 件設置伸展因子,會影響到全部網格的控件排列,如果每行的控件都設置一些亂七八糟的伸展因子,那么整個網格的布局就無法預料了。
    我們應該從布局器的角度考慮界面劃分,布局器則通常管理多個控件的一大片區域,通過布局器來設置各個子條目的伸展因子,就能從宏觀角度合理分配空間,決定各個子條 目按多大的比例進行拉伸。


    (2)水平和垂直布局器的伸展因子設置


    QHBoxLayout 和 QVBoxLayout 都是通過基類 QBoxLayout 的函數設置內部直屬的各個控件和子布局的伸展因子,對應的設置函數為:

    1. void setStretch(int index, int stretch)

    2. bool setStretchFactor(QWidget * widget, int stretch)

    3. bool setStretchFactor(QLayout * layout, int stretch)

    第一個函數是設置序號為 index 的控件或子布局的伸展因子。
    第二個函數是設置布局器內部 widget 控件的伸展因子,使用這個函數設置伸展因子會覆蓋控件自身原來設置的伸展因子屬性。這個函數僅僅設置直屬的子控件,該布局器的子布局器內部的孫子控件是不管的。如果設置成 功就返回 true,如果 widget 不是該布局器的直屬子控件,那么會返回 false。
    第三個函數是設置內部子布局器 layout 的伸展因子。這個函數也是設置直屬的子布局器,而在子布局器內部的孫子布局器是不管的。如果設置正確就返回 true,否則返回 false。

    如果要獲取某個序號的控件或子布局器的伸展因子是多少,可以用如下函數:

    int stretch(int index) const


    在設計師或 QtCreator 設計模式,選中某個水平或垂直布局器,可以在右下角設置布局器的屬性欄:

    選中布局器之后,右下角屬性編輯欄可以看到 layoutStretch 一欄,里面是英文逗號分隔的數字,對應三個按鈕的情況,默認就是0,0,0;數字的個數與直屬的子控件和子布局器總共的計數是一致的,分別與各個序號的子控件和子布局對應。在上圖中,如果把 layoutStretch 設置為(注意是英文逗號)1,2,3;那么顯示效果就是:

    如果把 layoutStretch 設置為1,2,0那么顯示效果就變成:

    我們這里都是拿水平布局器作為例子示范,主要是因為很多控件的水平伸展策略都是可以拉伸的。
    而按鈕控件,默認在垂直方向上的伸展策略是 QSizePolicy::Fixed ,按鈕的高度是固定的,所以沒有拿垂直布局器舉例。在控件不能拉伸的情況,設置伸展因子就沒有用:

    上面都是以功能控件舉例的,控件通過 sizePolicy 屬性控制伸展策略,可以限定控件為固定高度等等。如果是子布局器,那么子布局器在水平和垂直方向通常都是可以拉伸的。因此伸展因子對直屬的子布局器總是有效的,而對固定高度或固定寬度的控件會出現失效的情況。


    (3)網格布局器的伸展因子設置


    網格布局器本身是二維的,它會始終保持控件在行和列上的對齊。不建議直接設置網格布局器內部控件的伸展因子屬性,因為改變一個控件的伸展因子屬性就會影響到全部的網格布局。應該通過網格布局器的函數或屬性來設置行或列的伸展因子。
    網格布局器為了保持網格的對齊特性,它都是整行或者整列第設置伸展因子:

    1. void setRowStretch(int row, int stretch)       //設置整行的伸展因子

    2. void setColumnStretch(int column, int stretch) //設置整列的伸展因子

    另外還可以設置某個整行的最小高度,或者設置某個整列的最小寬度:

    1. void setRowMinimumHeight(int row, int minSize)      //第 row 行最小高度設置為 minSize

    2. void setColumnMinimumWidth(int column, int minSize) //第 column 列的最小寬度設置為 minSize


    在設計師或 QtCreator 設計模式,可以設置網格布局器對應的四個特有屬性,如下所示:

    layoutRowStretch 就是各個行對應的伸展因子;
    layoutColumnStretch 就是各個列對應的伸展因子;
    layoutRowMinimumHeight 是各個行對應的最小高度;
    layoutColumnMinimumWidth 是各個列對應的最小寬度。

    如果我們把兩個列的伸展因子調整為1,3那么,得到效果就是:

    如果控件的寬度或者高度為固定的,那么網格控件也不會拉伸控件,比如上面按鈕的高度就是固定的,沒有被拉伸。在控件高度都不能拉伸時,設置網格布局器各個行的伸展因子也沒意義,比如下圖:

    在上圖里,雖然設置了 layoutRowStretch 為3,1但是兩行的占比其實是一樣的,因為兩行的控件在垂直方向都不能拉伸,垂直伸展因子就沒效果。如果上面四個格子不是按鈕控件,而是四個子布局器,那么兩個方向的伸展因子都會生效:

    上圖四個大格子,每個格子里都是水平布局器,每個水平布局器里放一個標簽和一個按鈕。
    每個格子都是子布局器的情況下,我們看到列的比例是 1:3 ,行的比例是 3:1 ,和右下角設置的比例就完全對上了。

    網格布局器的伸展因子設置就介紹到這,作為對比,我們提一下表單布局器。
    表單布局器因為第一列寬度固定,并且在垂直方向不拉伸,所以沒有設置伸展因子的函數和屬性,它只有設置域列增長策略的函數:

    void QFormLayout::setFieldGrowthPolicy(FieldGrowthPolicy policy)

    QFormLayout::setFieldGrowthPolicy() 我們在 6.4.1 小節講過了,感興趣的讀者可以去回顧一下,這里不重復介紹了。

    實際的布局中,其實伸展因子用的比較少,因為很少有遇到控件必須按照某些比例來拉伸的,尤其是控件的類型不同時,設置不同種類的控件拉伸比例,通常沒多大意義。實 際編程中最常用的是伸展策略。只有實際的功能控件有伸展策略相關的函數和屬性,布局器是沒有自己獨立的伸展策略的。

    對于伸展因子和伸展策略的運用,我們這里建議一個大致的分工原則:
    在實際布局中,如果要控制某個布局器直屬的子布局器、控件之間的拉伸比例,就通過布局器的伸展因子來設置;
    如果要控制功能控件是盡量拉伸還是盡量固定,那么通過控件自己的伸展策略屬性來設置。
     

    6.5.3 QSizePolicy 之二:伸展策略


    控件的 sizePolicy 屬性包括兩方面內容,上面介紹了第一方面的伸展因子,本小節是第二方面的伸展策略:

    屬性編輯欄里的水平策略和垂直策略就是本小節講解的伸展策略。伸展策略應用最多,也最復雜。

    QSizePolicy 關于伸展策略的內容可以分為兩個層級:


    (1)策略的基本標志位


    由 QSizePolicy::?PolicyFlag 類型枚舉,包括四個基本標志位:

    枚舉標志位數值描述
    QSizePolicy::GrowFlag1可增長標志,如果有必要的話,可以在建議尺寸之外繼續增長。
    QSizePolicy::ExpandFlag2盡量擴展標志,能占多大空間就占多大。
    QSizePolicy::ShrinkFlag4可收縮標志,如果有必要的話,可以在縮小到建議尺寸之后繼續縮小。
    QSizePolicy::IgnoreFlag8忽略建議尺寸,這個增長方式最野蠻,能占多大空間就占多大空間


    建議尺寸就是通過控件的 sizeHint() 函數獲取的尺寸,這個尺寸通常由 Qt 類庫自己根據要顯示的內容計算。建議尺寸是伸展策略的基準。
    控件通常不會直接設置策略的基本標志位,因為沒有這方面的設置函數。基本標志位的用途,是為了組合成為實用的策略枚舉常量,也就是下面第二層級的內容。


    (2)策略的枚舉常量


    伸展策略的枚舉常量由 QSizePolicy::?Policy 類型枚舉,有七個定義好的常量,用于設置控件的水平和垂直伸展策略:

    枚舉常量數值拉伸特點描述
    QSizePolicy::Fixed0固定以建議尺寸固定住,對于水平方向是固定寬度,垂直方向是固定高度。
    QSizePolicy::MinimumGrowFlag被動拉大以建議尺寸為最小尺寸,如果有多余的空間就拉伸,沒有多余的空間就保持建議尺寸。被動擴張。
    QSizePolicy::MaximumShrinkFlag被動縮小以建議尺寸為最大尺寸,窗口縮小時,如果其他控件需要,該控件可以盡量縮小為其他控件騰出空間。
    QSizePolicy::PreferredGrowFlag |
    ShrinkFlag
    被動伸縮以建議尺寸為最佳尺寸,能屈能伸,窗口縮小時可以為其他控件騰出空間,窗口變大時,也可以占據其他控件不需要的空閑空間?;?QWidget 默認是這種策略。被動擴張。
    QSizePolicy::ExpandingGrowFlag |
    ShrinkFlag |
    ExpandFlag
    主動擴張建議尺寸僅僅是明智的建議,但控件基本不采用。這個模式也是能屈能伸,但它傾向于主動擴張,它會盡可能占據新增的區域。
    QSizePolicy::MinimumExpandingGrowFlag |
    ExpandFlag
    主動擴張以建議尺寸作為最小尺寸,主動擴張,盡可能占據新增的區域。
    QSizePolicy::IgnoredShrinkFlag |
    GrowFlag |
    IgnoreFlag
    野蠻擴張忽略建議尺寸,雖然能屈能伸,但是它會盡最大可能占據空間。


    我們對七個策略常量大致分兩類,第一類是固定、單向縮小、單向拉大的,相同布局情景中,占據的尺寸大小排序為:

    QSizePolicy::MaximumQSizePolicy::FixedQSizePolicy::MinimumQSizePolicy::MinimumExpanding 。


    第二類是能屈能伸的,如果在相同布局情景中,占據尺寸大小排序為:

    QSizePolicy::PreferredQSizePolicy::ExpandingQSizePolicy::Ignored


    七個策略枚舉常量,最常用到的只有如下四個,我們考慮它們在相同布局場景中,占據的尺寸大小進行不嚴格排序(有例外):

    QSizePolicy::FixedQSizePolicy::PreferredQSizePolicy::MinimumQSizePolicy::Expanding


    雖然 Preferred 和 Expanding 都是能屈能伸的類型,但實際情況是只有窗口縮小到特別小的情況,這兩個才會比 Fixed 小。
    窗口如果特別小,那么窗口的可用性顯然受限,這通常屬于不合理的設置,因此正常情況下不會遇到 Preferred 和 Expanding 比 Fixed 占用空間小的情況。

    以上的策略枚舉常量是用于尺寸策略的設置函數中,控件和窗口的伸展策略細分為水平方向和垂直方向,通過如下兩個函數分別設置:

    1. void QSizePolicy::?setHorizontalPolicy(Policy policy)  //設置水平策略

    2. void QSizePolicy::?setVerticalPolicy(Policy policy)    //設置垂直策略

    水平和垂直策略在大多數情況下都是不相關的,各自管各自的維度。除了調用函數,設計師和 QtCreator 設計模式也可以直接設置控件的 sizePolicy 屬性兩個子屬性:"水平策略" 和 "垂直策略" 。

    伸展策略的常量有七個,每個常量都有各自的特性,我們在這里把它們簡化一下,在實際使用中可以按照下面三條建議來運用策略的枚舉常量:

    ① 如果希望控件尺寸在水平或垂直方向固定住,那么把該維度的策略設置為 QSizePolicy::Fixed。
    ② 如果希望控件被動拉伸,其他控件不需要空間時這個控件才會占據新增區域,那么可以用 QSizePolicy::Preferred (尺寸下限是隱含的最小建議尺寸)或者 QSizePolicy::Minimum(尺寸下限是建議尺寸)。
    ③ 如果希望控件盡量拉伸,主動擴張,那就把策略設置為 QSizePolicy::Expanding。


    Qt 里面的控件默認策略也是基本符合上面三條建議的,所以希望大家記住這三條建議,因為比較實用。
     

    6.5.4 QSizePolicy 之三:其他內容


    QSizePolicy 除了上面兩小節的伸展因子和伸展策略,還有一些其他的內容,這部分補充內容應用會比較少,但是會影響界面的一些細節,有必要在這講一下。


    (1)控件類型設置


    QSizePolicy::ControlType 枚舉類型有一大堆枚舉常量,大部分的 Qt 控件都對應一個枚舉常量,比如按壓按鈕對應的常量為 QSizePolicy::PushButton,單行編輯控件對應的枚舉常量是 QSizePolicy::LineEdit,類似的還 有很多,這里不列舉了。

    QSizePolicy 類中關于控件類型獲取和設置的函數為:

    1. ControlType QSizePolicy::?controlType() const

    2. void QSizePolicy::?setControlType(ControlType type)

    這個控件類型應用比較少,不是什么時候都生效的,而且對界面布局影響很小,只是一些細節有差異??丶愋椭粫灰恍┨囟ǖ?Qt 界面風格(可以查詢 QStyle 類文檔)采用,比如蘋果系統風格的 QMacStyle,不同的控件類型會影響各個控件之間的默認間隙。比如 Mac OS X Aqua 指導方針中指出按壓按鈕之間需要 12 像素的間隙,而垂直方向排布的單選按鈕間隔是 6 像素。因為控件類型影響很小,所以通常可以忽略這個設置。


    (2)建議尺寸的寬度和高度相關性設置


    多數情況下建議尺寸  sizeHint() 的高度和寬度是不相關的,但有些特殊情況,比如能夠自動換行的標簽控件、菜單欄(后面章節講解),比如一行長文本自動換行變成兩行時,高度是雙倍的,如果把標簽拉寬,當兩 行文本恢復成一行的時候,高度就變成單行的。這種控件越寬,它高度相對低一些,越窄,高度就高一些。因此這些控件的建議尺寸計算時,高度和寬度是相關的。
    可以通過如下函數設置在計算建議尺寸時,高度和寬度相關:

    void QSizePolicy::?setHeightForWidth(bool dependent)   //設置高度依賴寬度

    dependent 如果為 true,那么控件的建議尺寸高度就和寬度相關。如果 dependent 為 false 那么就是無關的。

    如果要獲知建議尺寸的高度是否與寬度相關,可以用如下函數:

    bool QSizePolicy::?hasHeightForWidth() const        //判斷高度是否依賴寬度


    另外還有一對相反功能的函數,計算建議尺寸時,寬度可能會依賴高度,這個設置只對 QGraphicsLayout 的子類有用,一般是用不到的:

    1. void QSizePolicy::?setWidthForHeight(bool dependent)  //設置寬度依賴高度

    2. bool QSizePolicy::?hasWidthForHeight() const          //判斷寬度是否依賴高度

    HeightForWidth 和 WidthForHeight 二者最多只能有一個生效,不能雙向依賴的。

    注意無論是 HeightForWidth 還是 WidthForHeight ,都只對建議尺寸的計算有影響,不會直接影響窗口或控件的高度和寬度拉伸比例。如果希望窗口或控件的高度和寬度保持一定比例,比如 2 : 3 ,那么這些函數是完全沒用的,因為根本不是一個概念。


    (3)控件隱藏時是否仍然占據布局空間


    程序運行時,控件都可以通過函數 hide() 隱藏自己。在控件隱藏時,控件是否還占據布局器里的空間,這是可以設置的:

    1. void QSizePolicy::?setRetainSizeWhenHidden(bool retainSize)  //設置控件在隱藏時是否仍占據布局器空間

    2. bool QSizePolicy::?retainSizeWhenHidden() const     //判斷隱藏控件是否占據布局器空間

    默認情況下,控件調用 hide() 隱藏之后,就不會在通過布局器分配空間了,因為沒有必要。
    如果遇到特殊情況需要保留隱藏控件在布局器里的占用的空間,可以用上述函數設置。
    如果設置保留隱藏控件的空間,那么布局器會留下一塊空白區域,就是控件在隱藏前應該占據的區域。


    (4)水平和垂直方向的設置互換


    為了應對可能的屏幕旋轉操作,QSizePolicy 提供了一個快捷函數,能夠把水平方向的伸展因子、伸展策略與垂直方向上的伸展因子、伸展策略完全互換過來:

    void QSizePolicy::?transpose()

    這個函數讀者可以根據實際情況試試。

    關于控件的尺寸調整策略就介紹這么多,下面通過兩個例子試一試伸展因子和伸展策略的功效。
     

    6.5.5 伸展策略對比示例


    這一小節通過兩個窗口來對比常用到的四個伸展策略枚舉常量,主界面的窗口里面是六個按鈕,點擊里面的第一個按鈕會彈出第二個示范窗口,第二個示范窗口里面放置六個 單行編輯控件。兩個窗口的布局器和各個控件的水平伸展策略都是一樣的,我們一方面對比四個常用策略的拉伸特性,另一方面對比按鈕和單行編輯控件對布局器和策略的不 同反應。

    打開 QtCreator,新建一個 Qt Widgets Application 項目,在新建項目的向導里填寫:
    ①項目名稱 comparepolicies,創建路徑 D:\QtProjects\ch06,點擊下一步;
    ②套件選擇里面選擇全部套件,點擊下一步;
    ③基類選擇 QWidget,點擊下一步;
    ④項目管理不修改,點擊完成。
    建好項目之后,打開窗體 widget.ui 文件,進入設計模式,按照下圖拖入六個按鈕:

    我們按從上到下、從左到右順序說明一下六個按鈕的屬性:
    ① 文本 "Fixed" ,對象名稱 pushButtonFixed ,水平策略選擇 Fixed 。
    ② 文本 "Preferred" ,對象名稱 pushButtonPreferred,水平策略選擇 Preferred 。
    ③ 文本 "Preferred2" ,對象名稱 pushButtonPreferred2,水平策略選擇 Preferred 。
    ④ 文本 "Minimum" ,對象名稱 pushButtonMinimum,水平策略選擇 Minimum 。
    ⑤ 文本 "Minimum2" ,對象名稱 pushButtonMinimum2,水平策略選擇 Minimum 。
    ⑥ 文本 "Expanding" ,對象名稱 pushButtonExpanding,水平策略選擇 Expanding 。

    設置好六個按鈕的屬性之后,我們對每個行進行布局,先對第一行兩個按鈕水平布局,第二行和第三行也一樣用水平布局,得到的效果如下:

    然后我們點擊主窗體空白區域,不選中任何控件和子布局器(其實就是唯一選中主界面窗口自身),直接點擊上面的垂直布局按鈕,自動為窗口設置主布局器:

    這樣主界面的布局就設置完畢。下面我們要為第一個 "Fixed" 按鈕添加一個 clicked() 信號的槽函數,等會我們在槽函數添加代碼來彈出第二個示范窗口:

    添加好槽函數之后,保存界面文件,我們回到代碼編輯模式,首先是編輯主窗體頭文件 widget.h ,我們要為第二個示范窗口添加成員指針和創建第二個示范窗口的函數:

    1. #ifndef WIDGET_H

    2. #define WIDGET_H

    3. #include <QWidget>

    4. namespace Ui {
    5. class Widget;
    6. }

    7. class Widget : public QWidget
    8. {
    9. Q_OBJECT

    10. public:
    11. explicit Widget(QWidget *parent = 0);
    12. ~Widget();

    13. private slots:
    14. void on_pushButtonFixed_clicked();

    15. private:
    16. Ui::Widget *ui;
    17. //第二個示范窗口,全部放置 QLineEdit
    18. QWidget *m_pWidget;
    19. //通過代碼構造第二個示范窗口
    20. void CreateWidget();
    21. };

    22. #endif // WIDGET_H

    m_pWidget 是我們自己用代碼構造的第二個示范窗口,CreateWidget() 就是負責構造第二個示范窗口的函數。頭文件里其他代碼行都是自動添加的。

    主窗體的界面不需要調整,我們剛才在設計模式都設置好了。我們下面編輯源代碼文件 widget.cpp 主要是為了構建第二個示范窗口的內容,并通過 "Fixed" 按鈕的槽函數彈窗顯示。
    在 widget.cpp 文件中,首先是頭文件包含和主窗體的構造函數:

    1. #include "widget.h"

    2. #include "ui_widget.h"
    3. #include <QLineEdit> //單行編輯器
    4. #include <QHBoxLayout> //水平布局器
    5. #include <QVBoxLayout> //垂直布局器
    6. #include <QDebug>

    7. Widget::Widget(QWidget *parent) :
    8. QWidget(parent),
    9. ui(new Ui::Widget)
    10. {
    11. ui->setupUi(this);
    12. //按鈕的建議尺寸和最小建議尺寸
    13. qDebug()<<tr("Preferred 按鈕:")
    14. <<ui->pushButtonPreferred->sizeHint()
    15. <<ui->pushButtonPreferred->minimumSizeHint();
    16. qDebug()<<tr("Expanding 按鈕:")
    17. <<ui->pushButtonExpanding->sizeHint()
    18. <<ui->pushButtonExpanding->minimumSizeHint();


    19. m_pWidget = NULL; //初始空指針
    20. CreateWidget(); //構建第二個示范窗口
    21. }

    我們新增了三個頭文件包含,是第二個示范窗口要用到的單行編輯器和水平布局器、垂直布局器。
    在構造函數里面,我們首先打印了 "Preferred" 按鈕和 "Expanding" 按鈕的建議尺寸和最小建議尺寸。
    因為這兩個按鈕都是能伸能屈的,建議尺寸是最優的尺寸,但是在需要伸縮的情況下,這兩個按鈕可能變大也可能變小。
    我們在設計模式沒有設置按鈕的最小尺寸 minimumSize,在這種情況下,minimumSizeHint() 尺寸會自動成為尺寸下限,按鈕縮小到這個最小建議尺寸,就不會再縮小。

    打印按鈕的信息之后,我們將 m_pWidget 初始化為空指針,然后調用 CreateWidget() 構建第二個示范窗口的界面。CreateWidget() 函數代碼等會講解。我們先看看析構函數的內容:

    1. Widget::~Widget()

    2. {
    3. //刪除第二個窗口
    4. if(m_pWidget != NULL)
    5. {
    6. delete m_pWidget; m_pWidget = NULL;
    7. }
    8. //刪除ui
    9. delete ui;
    10. }

    析構函數中,我們對 m_pWidget 做了判斷,如果是非空指針,就刪除第二個示范窗口,并把 m_pWidget 設為空。
    析構函數最后一句是原本自動生成的代碼,不用變。

    接下來是 CreateWidget() 函數,就是構建第二個示范窗口的代碼,我們沒有用新的 ui 文件,直接用代碼構建該示范窗口。這個函數內容比較多,我們按照幾個小塊來分開講解,首先是窗口新建和主布局器新建:

    //建立第二個示范窗口,包括內部的單行編輯控件和布局器

    1. //仿造主界面的架構,只是把按鈕換成單行編輯器
    2. void Widget::CreateWidget()
    3. {
    4. //構建第二個示范窗口
    5. m_pWidget = new QWidget(this, Qt::Window); //獨立窗口
    6. m_pWidget->resize(480, 360);
    7. m_pWidget->setWindowTitle(tr("單行編輯器的布局"));
    8. //主布局器是垂直排列的三行
    9. QVBoxLayout *mainLayout = new QVBoxLayout(m_pWidget);
    10. //待續

    主界面是不同水平伸展策略的按鈕,我們這第二個示范窗口則是不同水平伸展策略的單行編輯器。
    CreateWidget() 函數內,第一句是新建一個獨立的子窗口用于彈窗,注意 QWidget() 構造函數第二個參數,是窗口類型標志位,如果不設置標志位,那么 m_pWidget 會作為大部件顯示在主窗體內部,而在設置標志位是 Qt::Window 或 Qt::Dialog ,那么新建的 m_pWidget 才是獨立的子窗口,不會放在主窗體內部。

    然后我們把第二個示范窗口大小重置為 480*360 ,并設置該窗口標題為 "單行編輯器的布局" 。
    接著新建了主布局器,用于容納三個水平行的布局器。主布局器構造時指定了 m_pWidget 為父窗口指針。

    下面來看看第一行的控件和布局器代碼:

    1.  //構建六個單行編輯器,分成三行做對比

    2. //第一行
    3. //第一個是固定尺寸的
    4. QLineEdit *leFixed = new QLineEdit(m_pWidget);
    5. leFixed->setText(tr("Fixed"));
    6. QSizePolicy sp = leFixed->sizePolicy();
    7. //修改第一個的水平策略為 Fixed
    8. sp.setHorizontalPolicy(QSizePolicy::Fixed);
    9. leFixed->setSizePolicy(sp);

    10. //第二個編輯器
    11. QLineEdit *lePreferred = new QLineEdit(m_pWidget);
    12. lePreferred->setText(tr("Preferred"));
    13. sp = lePreferred->sizePolicy();
    14. //修改第二個的水平策略為 Preferred
    15. sp.setHorizontalPolicy(QSizePolicy::Preferred);
    16. lePreferred->setSizePolicy(sp);

    17. //第一行的布局器
    18. QHBoxLayout *lay1 = new QHBoxLayout();
    19. lay1->addWidget(leFixed); //添加第一個編輯器
    20. lay1->addWidget(lePreferred); //添加第二個編輯器
    21. //把第一行的布局器添加到主布局器
    22. mainLayout->addLayout(lay1);
    23. //待續

    第一個單行編輯器新建時是指定 m_pWidget 為父窗口,這樣該控件會由 m_pWidget 窗口管理。
    然后設置第一個單行編輯器的文本為 "Fixed" ,并把水平策略修改為 QSizePolicy::Fixed 。
    第一個編輯器的尺寸會固定為建議尺寸,不會被拉寬。

    第二個單行編輯器新建時也是指定 m_pWidget 為父窗口,然后設置文本為 "Preferred",修改水平策略為 QSizePolicy::Preferred,這個編輯器會被動地拉大或縮小。雖然沒有指定該編輯器最小尺寸,但是等會程序運行時我們會看到 "Preferred" 編輯器以隱含的最小建議尺寸為下限。

    然后我們新建了第一行的水平布局器 lay1,注意這個布局器沒有指定父窗口。
    我們把第一行的兩個編輯器添加給 lay1 ,然后把 lay1 添加到主布局器。

    下面看看第二行控件和布局器的代碼:

    1.    //第二行

    2. //第三個編輯器
    3. QLineEdit *lePreferred2 = new QLineEdit(m_pWidget);
    4. lePreferred2->setText(tr("Preferred2"));
    5. sp = lePreferred->sizePolicy();
    6. //修改第三個的水平策略為 Preferred
    7. sp.setHorizontalPolicy(QSizePolicy::Preferred);
    8. lePreferred2->setSizePolicy(sp);

    9. //第四個編輯器
    10. QLineEdit *leMinimum = new QLineEdit(m_pWidget);
    11. leMinimum->setText(tr("Minimum"));
    12. sp = leMinimum->sizePolicy();
    13. //修改第三個的水平策略為 Minimum
    14. sp.setHorizontalPolicy(QSizePolicy::Minimum);
    15. leMinimum->setSizePolicy(sp);

    16. //第二行的布局器
    17. QHBoxLayout *lay2 = new QHBoxLayout();
    18. lay2->addWidget(lePreferred2);
    19. lay2->addWidget(leMinimum);
    20. //添加到主布局器
    21. mainLayout->addLayout(lay2);
    22. //待續

    第三個單行編輯器也是以 m_pWidget 為父窗口,設置文本為 "Preferred2",修改水平策略為 QSizePolicy::Preferred。
    第四個單行編輯器也是以 m_pWidget 為父窗口,設置文本為 "Minimum",修改水平策略為 QSizePolicy::Minimum。
    然后新建了第二行的布局器 lay2 ,這個布局器沒有指定父窗口指針。
    接著將 lePreferred2 和 leMinimum 兩個編輯器添加給布局器 lay2 ,再把第二行布局器 lay2 添加到主布局器 mainLayout 。

    接下來是第三行控件和布局器的代碼:

    1.     //第三行

    2. //第五個編輯器
    3. QLineEdit *leMinimum2 = new QLineEdit(m_pWidget);
    4. leMinimum2->setText(tr("Minimum2"));
    5. sp = leMinimum2->sizePolicy();
    6. //修改第五個的水平策略為 Minimum
    7. sp.setHorizontalPolicy(QSizePolicy::Minimum);
    8. leMinimum2->setSizePolicy(sp);

    9. //第六個編輯器
    10. QLineEdit *leExpanding = new QLineEdit(m_pWidget);
    11. leExpanding->setText(tr("Expanding"));
    12. sp = leExpanding->sizePolicy();
    13. //修改第六個的水平策略為 Expanding
    14. sp.setHorizontalPolicy(QSizePolicy::Expanding);
    15. leExpanding->setSizePolicy(sp);

    16. //第三行的布局器
    17. QHBoxLayout *lay3 = new QHBoxLayout();
    18. lay3->addWidget(leMinimum2);
    19. lay3->addWidget(leExpanding);
    20. mainLayout->addLayout(lay3);
    21. //待續

    第五個單行編輯器也是以 m_pWidget 為父窗口,設置文本為 "Minimum2" ,修改水平策略為 QSizePolicy::Minimum。
    第六個單行編輯器也是以 m_pWidget 為父窗口,設置文本為 "Expanding",修改水平策略為 QSizePolicy::Expanding。
    然后新建了第三行的布局器 lay3 ,這個布局器沒有指定父窗口。
    接著把第三行的兩個編輯器 leMinimum2、leExpanding 添加到 布局器 lay3 ,并把 lay3 添加到主布局器 mainLayout。

    注意上面關于控件的代碼寫法:
    單行編輯控件的父窗口是 m_pWidget ,而不是布局器,也不能是布局器。
    布局器僅僅是輔助布局的手段,布局器不是實際的功能控件。
    布局器基類是 QLayoutItem,不能獨立存在,它需要依附于其他實體功能控件或窗口,但不會擁有任何控件,也就是不能作為父窗口。
    實體功能控件的基類是 QWidget,可以獨立存在,也可以借助布局器進行布局,QWidget 派生類控件可以作為其他控件的父窗口,可以擁有子控件。

    CreateWidget() 函數最后一小部分代碼是設置主布局器和打印調試信息的:

    1.     //設置該窗口的主布局器

    2. m_pWidget->setLayout(mainLayout);
    3. //如果只有一個布局器的 parent 設置為該窗口,那么可以不調用 setLayout()
    4. //上面的 setLayout() 一句其實可以省略,mainLayout 自動是主布局器

    5. //打印信息
    6. qDebug()<<tr("Fixed 編輯器建議尺寸:")<<leFixed->sizeHint();
    7. qDebug()<<tr("Preferred 編輯器建議尺寸:")<<lePreferred->sizeHint();
    8. qDebug()<<tr("Preferred 編輯器最小建議尺寸:")<<lePreferred->minimumSizeHint();
    9. qDebug()<<tr("Minimum 編輯器建議尺寸:")<<leMinimum->sizeHint();
    10. qDebug()<<tr("Expanding 編輯器建議尺寸:")<<leExpanding->sizeHint();
    11. qDebug()<<tr("Expanding 編輯器最小建議尺寸:")<<leExpanding->minimumSizeHint();
    12. }

    通常設置某個窗口的主布局器就是調用它的 setLayout() 函數,這是主動設置窗口主布局器的方式。
    還有第二種設置主布局器的方式,就是 ui_*.h 里面采用的方式,當有且只有一個布局器將父窗口指針設置為窗口 m_pWidget 時,這個布局器就自動成為 m_pWidget 的主布局器了。
    我們之前代碼里的 lay1、lay2、lay3 構造時都沒有父窗口指針,只有 mainLayout 指定了父窗口為 m_pWidget,其實 mainLayout 已經成為 m_pWidget 主布局器了,因此上面的 setLayout() 一句代碼可以省略。

    最后幾句 qDebug() 打印了 "Fixed" 和 "Minimum" 編輯器的建議尺寸,并打印了 "Preferred" 和 "Expanding" 編輯器的建議尺寸和最小建議尺寸。

    CreateWidget() 函數代碼就是上面那些。 程序兩個窗口的控件個數和布局格式是一樣的,但第二個示范窗口的代碼其實已經不少了。而我們通過設計模式生成的主界面窗口,就沒編寫什么代碼。可見通過 Qt 設計師和 QtCreator 設計圖形界面是很方便的,節省了很多關于新建控件、布局器等重復無聊的代碼。

    源代碼文件 widget.cpp 最后一部分是我們主界面第一個按鈕的槽函數代碼:

    1. //點擊按鈕彈出第二個窗口

    2. void Widget::on_pushButtonFixed_clicked()
    3. {
    4. if(m_pWidget != NULL)
    5. {
    6. m_pWidget->show(); //顯示
    7. }
    8. }

    這個槽函數非常簡單,就是判斷 m_pWidget 是否非空,如果非空就彈出該窗口。
    操作指針之前判斷一下指針非空,有利于增加程序的健壯性,以免操作空指針。

    整個例子的代碼到這里就完整了。主界面的窗口其實完全靠 QtCreator 設計模式完成的,而第二個示范窗口是完全靠手動編寫代碼實現的。下面生成并運行例子看看,先看主界面窗口:

    在主界面窗口比較大時,明顯看到第一行的 "Fixed" 按鈕比較窄,而 "Preferred" 按鈕比較寬。因為 "Fixed" 按鈕寬度是固定的,不能拉伸,因此水平布局器只能嘗試拉伸 "Preferred" 按鈕,正好 "Preferred" 按鈕能夠被動拉伸,就被拉寬了。
    第二行的 "Preferred" 按鈕和 "Minimum" 按鈕是等寬的,因為二者都是被動拉伸,誰也不占上風,就平均拉伸。
    第三行的 "Minimum" 按鈕屬于被動拉伸,而 "Expanding" 按鈕屬于主動拉伸,所有額外的空間都被 "Expanding" 按鈕占據了,"Minimum" 按鈕僅保持了建議尺寸。

    我們把主界面窗口縮到最小尺寸,可以看到下圖效果:

    注意,"Fixed" 按鈕和 "Minimum" 按鈕的尺寸下限是建議尺寸 sizeHint(),
    而 "Preferred" 和 "Expanding" 按鈕尺寸下限是最小建議尺寸 minimumSizeHint()。
    上圖中六個按鈕最小情況下都是一樣大的,因為按鈕的建議尺寸和最小建議尺寸是一樣大的,我們可以在輸出面板看到按鈕的尺寸信息:

    1. "Preferred 按鈕:" QSize(75, 23) QSize(75, 23)

    2. "Expanding 按鈕:" QSize(75, 23) QSize(75, 23)

    對于按鈕組成的布局器,四種常用伸展策略是符合下面公式的:
    QSizePolicy::Fixed ≤ QSizePolicy::Preferred ≈ QSizePolicy::Minimum ≤ QSizePolicy::Expanding

    主窗口的三行按鈕對比完畢。我們下面點擊主界面第一個 "Fixed" 按鈕進行彈窗,看到第二個示范窗口:

    在窗口比較大時,六個編輯器的拉伸特性和主窗口沒區別,都符合上面的公式。
    下面我們把第二個示范窗口縮到最小,再看看效果:

    這時候就明顯看到 "Fixed" 和 "Minimum" 編輯器保持一個建議尺寸,不會再變小。
    而 "Preferred" 和 "Expanding" 編輯器已經縮到比建議尺寸更小了,這兩個可伸縮的編輯器的尺寸下限是由最小建議尺寸指定的。我們可以在 調試輸出信息里看到:

    1. "Fixed 編輯器建議尺寸:" QSize(133, 20)

    2. "Preferred 編輯器建議尺寸:" QSize(133, 20)

    3. "Preferred 編輯器最小建議尺寸:" QSize(39, 18)

    4. "Minimum 編輯器建議尺寸:" QSize(133, 20)

    5. "Expanding 編輯器建議尺寸:" QSize(133, 20)

    6. "Expanding 編輯器最小建議尺寸:" QSize(39, 18)

    單行編輯器的建議尺寸都是 133*20,最小建議尺寸是 39*18 。
    因為單行編輯器的最小建議尺寸比普通的建議尺寸更小,因此上面的公式在窗口特別小的時候不成立。
    不過窗口特別小的時候,控件的可用性已經大大降低了,單行編輯器連一個單詞都顯示不完整了,這種情況在實際應用中是很少遇見的。

    本小節的例子就是為了印證 6.5.3 小節關于常用伸展策略的三條建議,伸展策略的枚舉常量原本有七個,我們把七個策略常量簡化為三條使用建議,希望大家記住這三條建議,到實際布局時會比較實用。
     

    6.5.6 圖標使用示例的布局設置


    本小節是對上一章 5.6.3 小節的圖標使用示例進行布局,我們簡單示范一下布局器的伸展因子和伸展策略用法。
    我們復制 D:\QtProjects\ch05\ 目錄里面的 helloqrc 文件夾,粘貼到第 6 章的示例目錄 D:\QtProjects\ch06\ ,然后進行下面操作:
    ① 把新的 helloqrc 文件夾重命名為 helloqrcnew ,并刪除里面的 helloqrc.pro.user 用戶文件。
    ② 把 helloqrcnew 文件夾里面的 helloqrc.pro 重命名為 helloqrcnew.pro 。
    ③ 用記事本打開新的 helloqrcnew.pro 文件,修改里面的 TARGET 一行,變成下面這句:

    TARGET = helloqrcnew

    這樣就得到新項目 helloqrcnew ,我們用 QtCreator 打開這個新項目,在配置項目界面選擇所有套件并點擊 "Configure Project" ,配置好項目后,打開 widget.ui 界面文件,進入 QtCreator 設計模式:

    這個界面的布局思路大概是這樣的,我們把上面三行用網格布局器排布,第一列和第二列的伸展因子比例設置為 1:3 ,這樣在窗口拉大時,標簽占 1/4,右邊輸入控件占 3/4。我們之前 6.3.2 和 6.4.2 小節的個人信息收集示例布局都出現了標簽控件很窄,而右邊輸入控件很寬,看著有點別扭。通過網格布局器的伸展因子比例設置,可以把標簽也拉寬些。這樣在窗口比較大時,整體 界面不會太別扭。
    第四行的兩個按鈕,我們用水平布局器封裝,然后把網格布局器與按鈕布局器組合成一個垂直布局器,作為窗口的主布局器。

    下面我們開始操作:
    (1)選中兩個單選按鈕,點擊上面的水平布局按鈕,把單選按鈕組合到一塊:

     
    (2)我們選中前三行的控件和單選按鈕布局器,點擊上面的網格布局按鈕,實現網格布局:

     

    實現網格布局后,把該網格布局器的列伸展因子 layoutColumnStretch 調整為1,3這樣標簽占 1/4 ,右邊一列占 3/4 。

    (3)我們選中兩個按壓按鈕,點擊上面的水平布局工具按鈕,實現水平布局:

     

    (4) 我們點擊主窗體空白區域,不選中任何控件(其實就是唯一選中主界面窗口自身),直接點擊上面的垂直布局按鈕,得到下圖的效果:

     

    目前這個界面不是我們想看到的,首先是下面的按鈕布局器太高了,而且按鈕也拉得太寬。

    (5)下面按鈕部分微調:
    我們選中 "提交" 按鈕,把它的水平策略調整為 Fixed;
    我們選中 "取消" 按鈕,把它的水平策略也調整為 Fixed。得到下圖效果:

    然后我們點擊主窗體的空白區域,選中主窗體本身,可以看到主布局器屬性欄,把垂直布局器的 layoutStretch 伸展因子設置為:3,1這樣讓網格布局器占據垂直方向大部分區域:

    現在下面兩個按鈕的布局問題算是解決了。上面網格布局器還是有問題,第二行的單選按鈕布局器占據了太大空間,而不是我們希望的每行各占三分之一。

    (6)網格布局器細節調整
    對于上面的網格布局器,我們希望三行各占三分之一,最直觀的想法是設置垂直方向的伸展因子。
    因為界面里多個布局器嵌套,選中某個子布局器的操作其實不好實現。
    我們直接在右上角的布局樹,點擊 gridLayout 條目,就可以很快捷地選中該網格布局器,然后把垂直方向的行伸展因子  layoutRowStretch 設置為1,1,1得到下圖的效果:

    這里看到設置三個行的伸展因子并沒有效果,因為右邊一列的單行編輯控件和組合框在垂直方向都是固定高度的,而中間的單選按鈕布局器默認是盡量拉伸,所以即使設置了 行的伸展因子也沒有用。
    如果我們修改右邊單行編輯控件和組合框的垂直伸展策略為主動擴張,那么這兩個控件會被拉得很高,但是只顯示一行文本,從顯示上看會非常別扭。

    我們的視野不要局限在右邊一列,可以從左邊一列的標簽控件來打主意。
    標簽在垂直方向默認都是 Preferred 被動拉伸的策略,如果我們把左邊一列三個標簽的垂直策略全部設置成 Expanding,讓三個標簽都去主動占據垂直方向的空間,那么會有驚喜出現:

    這樣就得到了我們想要的布局效果了。
    我們保存界面文件,然后生成運行例子,看看運行效果:


    最后順便提一下,如果讀者希望標簽的文本在水平方向居中,是可以設置標簽控件的 alignment 屬性的,調整為水平居中 AlignHCenter 即可。修改界面后要點擊 QtCreator 菜單【構建-->重新構建 "項目名"】,然后就可以看到文本水平居中的標簽。讀者可以自行測試一下,這里不再截圖示范了。

    本小節的例子同時示范了伸展策略和伸展因子的運用,另外,布局時不但可以從我們需要調整的列考慮,還可以從相鄰的列角度考慮問題,比如要調整第二列的輸入控件布 局,其實可以調整第一列標簽控件的垂直策略來實現我們想要的效果。思維可以開闊一些,旁敲側擊有時候也是好方法。
     

      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 高大丰满熟妇丰满的大白屁股| 一区二区国产高清视频在线| 精品一卡2卡三卡4卡乱码精品视频| 九九在线精品国产| 中文字幕有码无码AV| 国产精品天干天干综合网| 潮喷失禁大喷水无码| 久久丫精品国产亚洲AV| 中文字幕有码日韩精品| 菠萝菠萝蜜午夜视频在线播放观看| 亚洲成AV人片不卡无码手机版| 免费看欧美全黄成人片| 久亚洲一线产区二线产区三线产区| 国产一区二区一卡二卡| 亚洲一区二区三区无码中文字幕 | 99久久免费精品国产72精品九九 | 乱妇乱女熟妇熟女网站| 免费av深夜在线观看| 日本一道本高清一区二区| 国产日韩精品中文字幕| 久久亚洲中文字幕伊人久久大 | 久久精品国产亚洲AV忘忧草18| 亚洲国产在一区二区三区| 白嫩少妇激情无码| A男人的天堂久久A毛片| xxxx丰满少妇高潮| 国产裸体XXXX视频在线播放| 亚洲精品一区二区天堂| 国产又爽又粗又猛的视频| 真实国产老熟女无套中出| 福利一区二区不卡国产| 国产精品V欧美精品V日韩精品| 国产又黄又湿又刺激网站| 人成午夜免费大片| 亚洲 另类 日韩 制服 无码| 在线高清免费不卡全码| 中文成人无码精品久久久| 国产裸体美女视频全黄| 宅男噜噜噜66在线观看| 99久久亚洲综合精品成人网| 国产AV激情久久无码天堂|