duilib入門簡明教程 -- 界面佈局(9)

   上一個教程實現的標題欄代碼中,並沒有看到處理自適應窗口大小的代碼,但是窗口大小變化後,按鈕的位置會跟着變化,這是因爲我們將按鈕放到了HorizontalLayout、VerticalLayout,這樣duilib就會幫我們自動佈局按鈕的位置和大小,顧名思義,HorizontalLayout就是水平佈局,VerticalLayout就是垂直佈局。


    最開始的教程裏面,窗口大小變化時,Hello World按鈕會沾滿整個窗口,並且文字始終居中,這就是HorizontalLayout的效果:


<HorizontalLayout>   <Button name="btnHello" text="Hello World"/></HorizontalLayout>

    那麼HorizontalLayout和VerticalLayout有什麼區別呢? 其實這個Alberl也不怎麼懂,Alberl都是直接試效果的,HorizontalLayout不行就換VerticalLayout ~O(∩_∩)O  這個還得請各位大神多多賜教,等寫完這個入門教程後,Alberl會繼續學習duilib,到時候再繼續寫教程。

    由於官方木有文檔,所有的東西都靠自己去看,去Demo裏調試,所以這個佈局的準確文字定義我也不好說,就直接用實驗的方式跟大家講解啦~

 

    現在開始講解上一個教程中的界面佈局:

    1、首先得到一個漸變的背景窗口,將XML的內容改成下面這樣


<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">    <VerticalLayout bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">    </VerticalLayout></Window>

效果如圖:

圖片

    從duilib的源碼裏可以看到:

    (1)XML的 <VerticalLayout> 節點對應於duilib裏的CVerticalLayoutUI控件

    (2)CVerticalLayoutUI控件繼承於CContainerUI,而CContainerUI繼承於CControlUI。


    所以其實CVerticalLayoutUI 也是一個控件啦,把它和CButtonUI同等對待,就比較好理解了。

爲了進一步表現他們的類似,可以將XML裏面的VerticalLayout 換成 Button、Control、Container 試試,你會發現效果是一樣的哦~

 

    再次強調下win32/MFC的界面 和duilib 界面的區別:

    (1)MFC中將按鈕、菜單、標題欄等等都當作不同的東西(例如標題欄只能放在最上面,按鈕不能直接拖到標題欄等等);


     duilib中將所有的東西都同等對待,所以處理起來非常方便(別說把按鈕放到標題欄上,就算把標題欄放在按鈕上都沒問題)。


    (2)MFC中所有的窗口和控件都是繼承於CWnd(win32繼承於HWND)。


     duilib中所有的控件都繼承於CControlUI,所有的窗口都繼承於CWindowWnd(內部包裝了HWND)。


     所以如果用MFC做一個界面,那麼上面就是很多個CWnd,用Spy++可以看到不同的窗口句柄。


     如果用duilib做一個界面,那麼上面就是很多個CControlUI,但是用Spy++只能看到一個窗口句柄。


     這是因爲duilib整個窗口只有一個HWND,其他的CControlUI雖然是控件,但是其實都是自己繪製出來的,並不是真正的HWND,所以你可以把這些控件理解爲自繪,整個duilib的界面繪製,就是在自繪一個HWND。

 

    2、加上標題欄,將XML的內容改成下面這樣:

<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout  bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">        <!-- 標題欄區 -->        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">          </HorizontalLayout>    </VerticalLayout ></Window>

效果如圖:

圖片

其中height="32" 是指這個HorizontalLayout 只佔用32個像素高度。

 

    3、將標題欄移到下面,將XML的內容改成下面這樣:

<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout  bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">        <HorizontalLayout /> <!-- 佔空位,佔據上面所有的空位-->         <!-- 標題欄區 -->        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">          </HorizontalLayout>    </VerticalLayout ></Window>

效果如圖:

圖片

這裏只加了一行代碼<HorizontalLayout />,就讓標題欄移到了下面,這行代碼的意思是:佔據空白的部分。


由於這行代碼放在標題欄HorizontalLayout 的上面,所以標題欄被擠了下去,如果放到下面,是沒有效果的。

 

4、將標題欄移到中間,將XML的內容改成下面這樣:

<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout  bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">        <HorizontalLayout /> <!-- 佔空位,佔據上面所有的空位-->         <!-- 標題欄區 -->        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">          </HorizontalLayout>         <HorizontalLayout /> <!-- 佔空位,佔據下面所有的空位-->    </VerticalLayout ></Window>

效果如圖:

圖片

    爲什麼標題欄就跑到中間了呢? 


    在標題欄的上面和下面都有一個佔空位的<HorizontalLayout />,如果沒有指定高度,那麼他們會默認各佔一半高度,相當於有一個默認的屬性 height="***"

 

    那麼我們給它指定一個高度試試,比如把上面那個<HorizontalLayout /> 改爲<HorizontalLayout height="32" />,效果如圖:

圖片

 

    現在應該明白<HorizontalLayout />佔位的作用了吧~\(^o^)/~

    這裏有一點要注意的就是:


佔位的時候,

<HorizontalLayout /> 一般是指定height屬性,也就是說佔的位置是從上往下算的。因爲水平方向的位置都會佔據。


<VerticalLayout/>       一般是指定width屬性,也就是說佔的位置是從左往右算的。因爲垂直方向的位置都會佔據。


並且HorizontalLayout 和VerticalLayout一般都是交叉包含,而不是重複包含(比如<HorizontalLayout> 子節點裏再包含一個<HorizontalLayout> 節點)。


    當然,上面指的是一般情況,如果對佈局很熟悉了,就可以隨意包含了。


    這裏講的都是把標題欄水平放置,把標題欄垂直放置相信也難不倒大家了,就請自行試驗,以便熟悉這些佈局。

 

    5、回到前面第2個步驟,我們來添加客戶區佈局。

    因爲背景色已經是漸變的了,所以就不給客戶區加背景了,那麼客戶區暫且不管。

 

    6、添加最大化、最小化、關閉按鈕:

    上一個教程的最後部分已經解釋了按鈕的外觀等屬性,這裏爲了簡明,就不加那麼多屬性了,先加上一個最小化按鈕試試效果:

<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout  bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">        <!-- 標題欄區 -->        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">              <Button name="minbtn" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>        </HorizontalLayout>    </VerticalLayout ></Window>

效果如圖:

圖片

可以看到整個最小化按鈕都被拉伸了,其中兩邊的矩形色塊是因爲圖片的邊框也被拉伸了。

 

我們再加上最大化按鈕和關閉按鈕,XML如下:

<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout  bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">        <!-- 標題欄區 -->        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">              <Button name="minbtn" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>            <Button name="maxbtn" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>            <Button name="closebtn" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>        </HorizontalLayout>    </VerticalLayout ></Window>

效果如圖:

圖片

    可以發現三個按鈕被均勻拉伸了。


    但是我們顯然不想讓按鈕被拉伸,怎麼辦呢?


    還記得前面說的佔位佈局嗎?因爲我們想讓按鈕顯示到右邊,所以我們要佔住左邊的部分。 那我們加一個佔位試試。


不過,

    (1)親們知道這個佔位要加到哪一行麼?

        當然是加到按鈕的上面! 那我們加到按鈕上面試試。


    (2)親們知道這個佔位佈局用<HorizontalLayout/>還是<VerticalLayout/>麼?

        其實我也不知道,那咱們就試試吧。


        先加個<HorizontalLayout/>玩玩,XML如下:

<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout  bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">               <!-- 標題欄區 -->        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">              <HorizontalLayout />            <Button name="minbtn" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>            <Button name="maxbtn" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>            <Button name="closebtn" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>        </HorizontalLayout>    </VerticalLayout ></Window>

效果如圖:

圖片

    (其實換成VerticalLayout等任何CControlUI,效果都是一樣的)


    果然佔到了左邊的部分,但是爲什麼還是均分呢,怎麼讓它只佔用左邊的一大部分呢?


    這就是width的用處了, 我們給HorizontalLayout 加上一個屬性 width = "600",可以看到如下效果:

圖片

    好傢伙,果然有用!


    下一步我們再把width加大一點,應該就可以讓按鈕正常了吧?


    先別急着管大小,我們先拖動一下窗口大小,或者點擊最大化按鈕~


    是不是有新問題啦? 爲什麼按鈕還是被放大了呢?


    因爲我們給HorizontalLayout加上了width屬性,那麼在水平方向,它就失去自適應效果啦,因爲寬度永遠是前面指定的600.


    那怎麼樣才能讓按鈕不被放大呢?


    很顯然,不應該給左邊的佔位佈局HorizontalLayout 指定width屬性,而應該給右邊的按鈕指定width屬性。


    但是按鈕有 width屬性嗎?


    按鈕是有,但是我們應該添加一個佔位佈局 HorizontalLayout  來指定width屬性。 XML如下:

<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout  bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">               <!-- 標題欄區 -->        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">              <HorizontalLayout />            <HorizontalLayout width = "77">                <Button name="minbtn" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>                <Button name="maxbtn" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>                <Button name="closebtn" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>            </HorizontalLayout>        </HorizontalLayout>    </VerticalLayout ></Window>

效果如圖:

圖片

    現在窗口大小怎麼變,按鈕都不會被拉伸啦,恭喜小夥伴們~

    可以看到那3個Button節點都被放到了HorizontalLayout 節點下,下面是時候講一下佈局了:

    其實duilib整個界面都是由各種佈局組成,我們把上面的XML簡化一下,就是下面這樣子:

<Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout >               <HorizontalLayout height="32" >              <HorizontalLayout />            <HorizontalLayout width = "77" />        </HorizontalLayout>    </VerticalLayout ></Window>

    很明顯,最外層是整個窗口的佈局<VerticalLayout>,之後又包含了一個 <HorizontalLayout height="32" >佈局(即標題欄),

再裏面又包含了兩個HorizontalLayout佈局,所以一切框架和位置都是由佈局決定。

    這裏先簡要介紹一下duilib的UI設計器:


    1、在duilib源碼的bin目錄下,【DuiDesigner.exe】就是UI設計器啦。

    2、把XML拖拽上去即可直接看到界面效果,


    我們把前面那個完整的XML拖進去,即可看到如下效果:

圖片

    紅色邊框圍起來的就是一個個HorizontalLayout 等佈局啦~

 

    7、調整按鈕的位置和大小。

    雖然已經將按鈕顯示到最後邊,但是按鈕沾滿了右邊部分,我們現在把他們的高度調小一點:

    給Button節點都加上屬性 height ="20",效果如圖:

圖片

    嗯,效果看起來還行。

 

    再加上width="23"屬性,效果如圖:

圖片

    那怎麼樣讓按鈕不挨着頂部呢?

    前面介紹過float屬性,是用於絕對定位,由於現在按鈕的位置都是由佈局自動調整的,所以沒辦法調節位置,如果不想讓佈局自動調整位置,就要加上float="true",這樣就可以自己指定位置啦。我們給最小化按鈕加上 float="true" pos="0,5,22,24" 試試,效果如圖:

圖片

 

    額,最小化按鈕哪裏去了~~~

    雖然最小化按鈕使用了絕對定位,但是其他兩個按鈕還是自動佈局,所以需要給他們也加上,XML如下:

<HorizontalLayout width = "77">                <Button name="minbtn"   height ="20" width="23" float="true" pos="0,5,22,24"  normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>                <Button name="maxbtn"   height ="20" width="23" float="true" pos="22,5,44,24" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>                <Button name="closebtn" height ="20" width="23" float="true" pos="44,5,74,24" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>            </HorizontalLayout>

效果如圖:

圖片

 

    對比一下上個教程完整的圖片:

圖片

    發現我們這個這個圖有點不對,三個按鈕的中間的線有點粗~

    這是因爲圖片畫的不對(這些圖片是Alberl早幾年畫的,用於MFC,所以並沒有考慮duilib),可以把最大化按鈕兩邊的邊框都去掉,這樣就OK啦~


    不過呢,沒必要那麼做,我們恰好可以再學習一點新知識~

    我們可以看到,雖然給關閉按鈕指定的寬度也是23,但是它卻比其他按鈕大。  這說明width屬性已經失效了,這是因爲我們在pos屬性裏面已經指定了位置大小,它會優先以pos屬性爲準,那麼顯然height屬性也失效了。(感謝網友【糖加三勺】的提醒,Alberl的這個說法有誤,重新試了一下,如果pos屬性放在後面,就會以pos爲準,height屬性放在後面就會以height爲準,並不是屬性失效。


    回到剛剛那個按鈕圖片的問題,由於每個按鈕圖片都畫了邊框,所以會有加在一起就有兩個邊框了,所以中間的線有點粗,那麼我們現在可以將最大化、關閉按鈕往左邊移動一個像素。

效果如圖:

圖片

    嘿嘿,好了吧~

    但是這個關閉按鈕貌似有點寬~

    我們當然可以再次調整pos屬性,但是這不科學~~

    還記得失效的那兩個屬性麼?


    那是因爲pos屬性的後面兩個值都填了非0值,所以導致那兩個屬性失效,下面我們把pos後面的兩個值改爲0試試。


可以發現那兩個屬性又生效啦~(感謝網友【糖加三勺】的提醒,Alberl的這個說法有誤,重新試了一下,如果pos屬性放在後面,就會以pos爲準,height屬性放在後面就會以height爲準,並不是屬性失效。

    現在只要去掉width、height屬性中的一個,按鈕都會不見了,Alberl以爲按鈕的大小會調整成圖片的大小呢~~~


看來只能指定寬度和高度了(爲了方便後期的位置調整,建議pos屬性後面兩個值填0,使用width/height屬性來指定按鈕大小)


這幾個圖片的寬高分別是19 * 23、19*28,所以就手動指定了,XML如下:

<?xml version="1.0" encoding="UTF-8"?><Window size="800,600" mininfo="600,400" caption="0,0,0,32" sizebox="4,4,4,4">     <VerticalLayout  bkcolor="#FFF0F0F0" bkcolor2="#FFAAAAA0">               <!-- 標題欄區 -->        <HorizontalLayout height="32" bkcolor="#FFE6E6DC" bkcolor2="#FFAAAAA0">              <HorizontalLayout />            <HorizontalLayout width = "77">                <Button name="minbtn"   float="true" pos="0,5,0,0"  height="19" width="23" normalimage=" file='SysBtn\MinNormal.bmp' " hotimage=" file='SysBtn\MinFocus.bmp' "/>                <Button name="maxbtn"   float="true" pos="22,5,0,0" height="19" width="23" normalimage=" file='SysBtn\MaxNormal.bmp' " hotimage=" file='SysBtn\MaxFocus.bmp' "/>                <Button name="closebtn" float="true" pos="44,5,0,0" height="19" width="28" normalimage=" file='SysBtn\closeNormal.bmp' " hotimage=" file='SysBtn\closeFocus.bmp' "/>            </HorizontalLayout>        </HorizontalLayout>    </VerticalLayout ></Window>

效果如圖:

圖片

    (上面的XML裏,Button的父節點HorizontalLayout 換成 VerticalLayout也是一樣的效果,所以有時候他們是沒有什麼分別的,不過個人的理解應該是要交叉使用的)


    好啦,最關鍵的佈局部分講完啦,另外,在duilib的官方羣裏,有共享一個佈局案例,Alberl已整理出來【duilib入門和xml培訓 佈局案例.rar】,那裏有9個佈局案例,相信看完本教程的講解之後,再看看那9個XML佈局,應該就很熟悉佈局啦,如果還有不懂的話,請留言~


    注意:一切結果以實際運行效果爲準,切勿完全相信本文的言論,因爲Alberl搞不好手一抖打錯個字母啥的,或者複製上來的代碼有誤,或者本來理解就有誤,很可能會誤導大家。如有錯誤的地方,多謝指正~\(^o^)/~



圖片


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章