www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 芯聞號 > 充電吧
[導(dǎo)讀]Components(組件)? ? Component 是由 Qt 框架或開發(fā)者封裝好的、只暴露了必要接口的 QML 類型,可以重復(fù)利用。一個 QML 組件就像一個黑盒子,它通過屬性、信號、函數(shù)和外部

Components(組件)

? ? Component 是由 Qt 框架或開發(fā)者封裝好的、只暴露了必要接口的 QML 類型,可以重復(fù)利用。一個 QML 組件就像一個黑盒子,它通過屬性、信號、函數(shù)和外部世界交互。

? ? 一個 Component 即可以定義在獨立的 qml 文件中,也可以嵌入到其它的 qml 文檔中來定義。通常我們可以根據(jù)這個原則來選擇將一個 Component 定義在哪里:如果一個 Component 比較小且只在某個 qml 文檔中使用或者一個 Component 從邏輯上看從屬于某個 qml 文檔,那就可以采用嵌入的方式來定義該 Component 。你也可以與 C++ 的嵌套類對比來理解。

嵌入式定義組件

? ??《Qt Quick 事件處理之信號與槽》一文中使用到 Component 的示例 QML 代碼如下:

[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????width:?320;??????height:?240;??????color:?"#C0C0C0";????????????Text?{??????????id:?coloredText;??????????anchors.horizontalCenter:?parent.horizontalCenter;??????????anchors.top:?parent.top;??????????anchors.topMargin:?4;??????????text:?"Hello?World!";??????????font.pixelSize:?32;??????}????????????Component?{??????????id:?colorComponent;??????????Rectangle?{??????????????id:?colorPicker;??????????????width:?50;??????????????height:?30;??????????????signal?colorPicked(color?clr);??????????????MouseArea?{??????????????????anchors.fill:?parent??????????????????onPressed:?colorPicker.colorPicked(colorPicker.color);??????????????}??????????}??????}????????????Loader{??????????id:?redLoader;??????????anchors.left:?parent.left;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????sourceComponent:?colorComponent;??????????onLoaded:{??????????????item.color?=?"red";??????????}??????}????????????Loader{??????????id:?blueLoader;??????????anchors.left:?redLoader.right;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????sourceComponent:?colorComponent;??????????onLoaded:{??????????????item.color?=?"blue";??????????}??????}????????????Connections?{??????????target:?redLoader.item;??????????onColorPicked:{??????????????coloredText.color?=?clr;??????????}??????}????????????Connections?{??????????target:?blueLoader.item;??????????onColorPicked:{??????????????coloredText.color?=?clr;??????????}??????}??}??

? ? 其中,顏色選擇組件的定義代碼如下:

[javascript]?view plain?copyComponent?{??????id:?colorComponent;??????Rectangle?{??????????id:?colorPicker;??????????width:?50;??????????height:?30;??????????signal?colorPicked(color?clr);??????????MouseArea?{??????????????anchors.fill:?parent??????????????onPressed:?colorPicker.colorPicked(colorPicker.color);??????????}??????}??}??
? ? 如你所見,要在一個 QML 文檔中嵌入 Component 的定義,需要使用 Component 對象。

? ? 定義一個 Component 與定義一個 QML 文檔類似, Component 只能包含一個頂層 item ,而且在這個 item 之外不能定義任何數(shù)據(jù),除了 id 。比如上面的代碼中,頂層 item 是 Rectangle 對象,在 Rectangle 之外我定義了 id 屬性,其值為 colorComponent 。而頂層 item 之內(nèi),則可以包含更多的子元素來協(xié)同工作,最終形成一個具有特定功能的組件。

? ? Component 通常用來給一個 view 提供圖形化組件,比如 ListView::delegate 屬性就需要一個 Component 來指定如何顯示列表的每一個項,又比如 ButtonStyle::background 屬性也需要一個 Component 來指定如何繪制 Button 的背景。?

? ? Component 不是 Item 的派生類,而是從 QQmlComponent 繼承而來,雖然它通過自己的頂層 item 為其它的 view 提供可視化組件,但它本身是不可見元素。你可以這么理解:你定義的組件是一個新的類型,它必須被實例化以后才可能顯示。而要實例化一個嵌入在 qml 文檔中定義的組件,則可以通過 Loader 。后面我們詳細講述 Loader ,這里先按下不表,我們要來看如何在一個文件中定義組件了。

在單獨文件中定義組件

? ? 很多時候我們把一個 Component 單獨定義在一個 qml 文檔中,比如 Qt Quick 提供的 BusyIndicator 控件,其實就是在 BusyIndicator.qml 中定義的一個組件。下面是 BusyIndicator.qml 文件的內(nèi)容:

[javascript]?view plain?copyControl?{??????id:?indicator????????property?bool?running:?true????????Accessible.role:?Accessible.Indicator??????Accessible.name:?"busy"????????style:?Qt.createComponent(Settings.style?+?"/BusyIndicatorStyle.qml",?indicator)??}??
? ? 我在《Qt Quick 簡單教程》一文中的顯示網(wǎng)絡(luò)圖片實例中,使用了 BusyIndicator 來提示用戶圖片正在加載中需要等候,你可以跳轉(zhuǎn)到那篇文章學(xué)習(xí) BusyIndicator 的用法。

? ? BusyIndicator 組件的代碼非常簡單,只是給 Control 元素(Qt Quick 定義的私有元素,用作其它控件的基類,如 ComboBox 、 BusyIndicator 等)增加了一個屬性、設(shè)置了幾個屬性的值,僅此而已。

? ? 不知你是否注意到了, BusyIndicator.qml 文件中的頂層 item 是 Control ,而我們使用時卻是以 BusyIndicator 為組件名(類名)。這是我們定義 Component 時要遵守的一個約定:組件名字必須和 qml 文件名一致。好嘛,和 Java 一樣啦,類名就是文件名。還有一點,組件名字的第一個字母必須是大寫。對于在文件中定義一個組件,就這么簡單了,再沒有其它的特殊要求。 Qt Quick 提供的多數(shù)基本元素和特性,你都可以在定義組件時使用。

? ? 一旦你在文件中定義了一個組件,就可以像使用標準 Qt Quick 元素一樣使用你的組件。比如我們給顏色選擇組件起個名字叫 ColorPicker ,對應(yīng)的 qml 文件為 ?ColorPicker.qml ,那么你就可以在其它 QML 文檔中使用 ColorPicker {...} 來定義 ColorPicker 的實例。

? ? 好啦,現(xiàn)在讓我們來看看在單獨文件中定義的 ColorPicker 組件:

[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????id:?colorPicker;??????width:?50;??????height:?30;??????signal?colorPicked(color?clr);????????????function?configureBorder(){??????????colorPicker.border.width?=?colorPicker.focus???2?:?0;????????????colorPicker.border.color?=?colorPicker.focus???"#90D750"?:?"#808080";???????}????????????MouseArea?{??????????anchors.fill:?parent??????????onClicked:?{??????????????colorPicker.colorPicked(colorPicker.color);??????????????mouse.accepted?=?true;??????????????colorPicker.focus?=?true;??????????}??????}??????Keys.onReturnPressed:?{??????????colorPicker.colorPicked(colorPicker.color);??????????event.accepted?=?true;??????}??????Keys.onSpacePressed:?{??????????colorPicker.colorPicked(colorPicker.color);??????????event.accepted?=?true;??????}????????????onFocusChanged:?{??????????configureBorder();??????}????????????Component.onCompleted:?{??????????configureBorder();??????}??}??

? ? 請注意上面的代碼,它和嵌入式定義有明顯不同: Component 對象不見咧!對,就是醬紫滴:在單獨文件內(nèi)定義組件,不需要 Component 對象,只有在其它 QML 文檔中嵌入式定義組件時才需要 Component 對象。另外,為了能夠讓多個 ColorPicker 組件可以正常的顯示焦點框,我還使用了 onClicked 信號處理器,新增了 onFocusChanged 信號處理器,在它們的實現(xiàn)中調(diào)用 configureBorder() 函數(shù)來重新設(shè)置邊框的寬度和顏色,新增 onReturnPressed 和 onSpacePressed 以便響應(yīng)回車和空格兩個按鍵。

? ? 你可以使用 Item 或其派生類作為組件的根 item 。 ColorPicker 組件使用 Rectangle 作為根 Item 。現(xiàn)在讓我們看看如實在其它文件中使用新定義的 ColorPicker 組件。我修改了上節(jié)的示例,新的 qml 文件被我命名為 component_file.qml ,內(nèi)容如下:

[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????width:?320;??????height:?240;??????color:?"#EEEEEE";????????????Text?{??????????id:?coloredText;??????????anchors.horizontalCenter:?parent.horizontalCenter;??????????anchors.top:?parent.top;??????????anchors.topMargin:?4;??????????text:?"Hello?World!";??????????font.pixelSize:?32;??????}????????????function?setTextColor(clr){??????????coloredText.color?=?clr;??????}????????????ColorPicker?{??????????id:?redColor;??????????color:?"red";??????????focus:?true;??????????anchors.left:?parent.left;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;????????????KeyNavigation.right:?blueColor;??????????KeyNavigation.tab:?blueColor;????????????onColorPicked:{??????????????coloredText.color?=?clr;??????????}????????????}????????????ColorPicker?{??????????id:?blueColor;??????????color:?"blue";??????????anchors.left:?redColor.right;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;????????????KeyNavigation.left:?redColor;??????????KeyNavigation.right:?pinkColor;??????????KeyNavigation.tab:?pinkColor;?????????}????????????ColorPicker?{??????????id:?pinkColor;??????????color:?"pink";??????????anchors.left:?blueColor.right;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;????????????KeyNavigation.left:?blueColor;??????????KeyNavigation.tab:?redColor;?????????}????????????Component.onCompleted:{??????????blueColor.colorPicked.connect(setTextColor);??????????pinkColor.colorPicked.connect(setTextColor);??????}??}??

? ? 可以看到, component_file.qml 使用 ColorPicker 組件的方式與使用 Rectangle 、 Button 、 Text 等標準 Qt Quick 組件完全一致:可以給組件指定唯一的 id ,可以使用錨布局,可以使用 KeyNavigation 附加屬性……總之,自定義的組件和 Qt Quick 組件并無本質(zhì)不同。不過需要注意的是,組件實例的 id 和組成組件的頂層 item 的 id 是各自獨立的,以上面的例子來看, redColor 和 colorPicker 是兩個不同的 id ,前者指代組件對象(雖然組件的定義沒有使用 Component ),后者指代 ColorPicker 的 Rectangle 對象。

? ? 上面的代碼還演示兩種使用 qml 自定義信號的方式, redColor 使用信號處理器, greeColor 和 pinkColor 則使用了 signal 對象的 connect() 方法連接到 setTextColor() 方法上。

? ? 我把 ColorPicker.qml 和 component_file.qml 放在同一個文件下面,否則可能會報錯。圖 1 是運行 "qmlscene component_file.qml" 命令 的效果:


? ? ? ? ? ? 圖 1 在文件中定義組件并使用

? ? 對于定義在單獨文件中的 Component ,除了可以像剛剛介紹的那樣使用,也可以使用 Loader 來動態(tài)加載,根據(jù)需要再創(chuàng)建對象。下面我們就來看 Loader 究竟是何方妖怪。

使用 LoaderLoader 的詳細介紹

? ? Loader 用來動態(tài)加載 QML 組件。

? ? Loader 可以使用其 source 屬性加載一個 qml 文檔,也可以通過其 sourceComponent 屬性加載一個 Component 對象。當你需要延遲一些對象直到真正需要才創(chuàng)建它們時, Loader 非常有用。 當 Loader 的 source 或 sourceComponent 屬性發(fā)生變化時,它之前加載的 Component 會自動銷毀,新對象會被加載。將 source 設(shè)置為一個空字符串或?qū)?sourceComponent 設(shè)置為 undefined ,將會銷毀當前加載的對象,相關(guān)的資源也會被釋放,而 Loader 對象則變成一個空對象。

? ? Loader 的 item 屬性指向它加載的組件的頂層 item ,比如 Loader 加載了我們的顏色選擇組件,其 item 屬性就指向顏色選擇組件的 Rectangle 對象。對于 Loader 加載的 item ,它暴露出來的接口,如屬性、信號等,都可以通過 Loader 的 item 屬性來訪問。所以我們才可以這么使用:

[javascript]?view plain?copyLoader{??????id:?redLoader;??????anchors.left:?parent.left;??????anchors.leftMargin:?4;??????anchors.bottom:?parent.bottom;??????anchors.bottomMargin:?4;??????sourceComponent:?colorComponent;??????onLoaded:{??????????item.color?=?"red";??????}??}??

? ? 上面的代碼在 Loader 對象使用 sourceComponent 屬性來加載 id 為 colorComponent 的組件對象,然后在 onLoaded 信號處理器中使用 item 屬性來設(shè)置顏色選擇組件的顏色。對于信號的訪問,我們則可以使用 Connections 對象,如下面的 qml 代碼所示:

[javascript]?view plain?copyConnections?{??????target:?redLoader.item;??????onColorPicked:{??????????coloredText.color?=?clr;??????}??}??
? ? 我們創(chuàng)建的 Connections 對象,其 target 指向 redLoader.item ,即指向顏色選擇組件的頂層 item —— Rectangle ,所以可以直接響應(yīng)它的 colorPicked 信號。

? ? 雖然 Loader 本身是 Item 的派生類,但沒有加載 Component 的 Loader 對象是不可見的,沒什么實際的意義。而一旦你加載了一個 Component , Loader 的大小、位置等屬性卻可以影響它所加載的 Component 。如果你沒有顯式指定 Loader 的大小,那么 Loader 會將自己的尺寸調(diào)整為與它加載的可見 item 的尺寸一致;如果 Loader 的大小通過 width 、 height 或 錨布局顯式設(shè)置了,那么它加載的可見 item 的尺寸會被調(diào)整以便適應(yīng) Loader 的大小。不管是哪種情況, Loader 和它所加載的 item 具有相同的尺寸,這確保你使用錨來布局 Loader 就等同于布局它加載的 item 。

? ? 我們改變一下顏色選擇器示例的代碼,兩個 Loader 對象,一個設(shè)置尺寸一個不設(shè)置,看看是什么效果。新的 qml 文檔我們命名為 loader_test.qml ,內(nèi)容如下:

[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????width:?320;??????height:?240;??????color:?"#C0C0C0";????????????Text?{??????????id:?coloredText;??????????anchors.horizontalCenter:?parent.horizontalCenter;??????????anchors.top:?parent.top;??????????anchors.topMargin:?4;??????????text:?"Hello?World!";??????????font.pixelSize:?32;??????}????????????Component?{??????????id:?colorComponent;??????????Rectangle?{??????????????id:?colorPicker;??????????????width:?50;??????????????height:?30;??????????????signal?colorPicked(color?clr);??????????????MouseArea?{??????????????????anchors.fill:?parent??????????????????onPressed:?colorPicker.colorPicked(colorPicker.color);??????????????}??????????}??????}????????????Loader{??????????id:?redLoader;??????????width:?80;?//?[1]??????????height:?60;//?[2]??????????anchors.left:?parent.left;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????sourceComponent:?colorComponent;??????????onLoaded:{??????????????item.color?=?"red";??????????}??????}????????????Loader{??????????id:?blueLoader;??????????anchors.left:?redLoader.right;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????sourceComponent:?colorComponent;??????????onLoaded:{??????????????item.color?=?"blue";??????????}??????}????????????Connections?{??????????target:?redLoader.item;??????????onColorPicked:{??????????????coloredText.color?=?clr;??????????}??????}????????????Connections?{??????????target:?blueLoader.item;??????????onColorPicked:{??????????????coloredText.color?=?clr;??????????}??????}??}??
? ? 注意上面的代碼中的注釋,方括號標準的 2 處修改,設(shè)置了紅色 Loader 的尺寸,效果如圖 1 所示:


? ? ? ? ? ? ? ? 圖 2 Loader 尺寸

? ? 如果 Loader 加載的 item 想處理按鍵事件,那么必須將 Loader 對象的 focus 屬性置 true 。又因為 Loader 本身也是一個焦點敏感的對象,所以如果它加載的 item 處理了按鍵事件,應(yīng)當將事件的 accepted 屬性置 true ,以免已經(jīng)被吃掉的事件再傳遞給 Loader 。我們來修改下 loader_test.qml ,加入對焦點的處理,當一個顏色組件擁有焦點時,繪制一個邊框,此時如果你按下回車或空格鍵,會觸發(fā)其 colorPicked 信號。同時我們也處理左右鍵,在不同的顏色選擇組件之間切換焦點。將新代碼命名為 loader_focus.qml ,內(nèi)容如下:

[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????width:?320;??????height:?240;??????color:?"#EEEEEE";????????????Text?{??????????id:?coloredText;??????????anchors.horizontalCenter:?parent.horizontalCenter;??????????anchors.top:?parent.top;??????????anchors.topMargin:?4;??????????text:?"Hello?World!";??????????font.pixelSize:?32;??????}????????????Component?{??????????id:?colorComponent;??????????Rectangle?{??????????????id:?colorPicker;??????????????width:?50;??????????????height:?30;??????????????signal?colorPicked(color?clr);??????????????property?Item?loader;??????????????border.width:?focus???2?:?0;????????????????border.color:?focus???"#90D750"?:?"#808080";???????????????MouseArea?{??????????????????anchors.fill:?parent??????????????????onClicked:?{??????????????????????colorPicker.colorPicked(colorPicker.color);??????????????????????loader.focus?=?true;??????????????????}??????????????}??????????????Keys.onReturnPressed:?{??????????????????colorPicker.colorPicked(colorPicker.color);??????????????????event.accepted?=?true;??????????????}??????????????Keys.onSpacePressed:?{??????????????????colorPicker.colorPicked(colorPicker.color);??????????????????event.accepted?=?true;??????????????}??????????}??????}????????????Loader{??????????id:?redLoader;??????????width:?80;??????????height:?60;??????????focus:?true;??????????anchors.left:?parent.left;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????sourceComponent:?colorComponent;??????????KeyNavigation.right:?blueLoader;??????????KeyNavigation.tab:?blueLoader;????????????????????onLoaded:{??????????????item.color?=?"red";??????????????item.focus?=?true;??????????????item.loader?=?redLoader;??????????}??????????onFocusChanged:{??????????????item.focus?=?focus;??????????}??????}????????????Loader{??????????id:?blueLoader;??????????anchors.left:?redLoader.right;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????sourceComponent:?colorComponent;??????????KeyNavigation.left:?redLoader;??????????KeyNavigation.tab:?redLoader;????????????????????onLoaded:{??????????????item.color?=?"blue";??????????????item.loader?=?blueLoader;??????????}??????????onFocusChanged:{??????????????item.focus?=?focus;??????????}??????????????}????????Connections?{??????????target:?redLoader.item;??????????onColorPicked:{??????????????coloredText.color?=?clr;??????????}??????}????????????Connections?{??????????target:?blueLoader.item;??????????onColorPicked:{??????????????coloredText.color?=?clr;??????????}??????}??}??

? ? 首先我讓顏色選擇組件處理按鍵事件(如忘記請參看《Qt Quick事件處理之鼠標、鍵盤、定時器》),收到回車和空格鍵時發(fā)出 colorPicked 信號。我還給顏色選擇組件定義了一個名為 loader 的屬性,以便鼠標點擊顏色選擇組件時可以改變 Loader 對象的焦點屬性。我們在 Loader 的 onLoaded 信號處理器中給顏色選擇組件的 loader 屬性賦值。

? ? 顏色選擇組件根據(jù)焦點狀態(tài)決定是否繪制邊框,當有焦點時繪制寬度為 2 的邊框。

? ? 對于 Loader ,我設(shè)置了 KeyNavigation 附加屬性,指定左右鍵和 tab 鍵如何切換焦點,而當焦點變化時,同步改變顏色選擇組件的焦點。最后我設(shè)置 redLoader 擁有初始焦點。

? ? 圖 2 是運行效果圖:


? ? ? ? ? ? ? ?圖 3 loader與按鍵、焦點

? ? 你可以使用 qmlscene loader_focus.qml 命令運行看看效果,鼠標點擊某個顏色選擇組件,會觸發(fā)焦點切換和邊框變化,左右鍵、 tab 鍵也會觸發(fā)焦點變化,而當一個顏色選擇組件擁有焦點時,回車、空格鍵都可以觸發(fā) "Hello World!" 改變顏色。

從文件加載組件

? ? 之前介紹 Loader 時,我們以嵌入式定義的 Component 為例子說明 Loader 的各種特性和用法,現(xiàn)在我們來看如何從文件加載組件。

? ? 對于定義在一個獨立文件中的 Component ,同樣可以使用 Loader 來加載,只要指定 Loader 的 source 屬性即可?,F(xiàn)在再來修改下我們的例子,使用 Loader 來加載 ColorPicker 組件。

? ? 新的 qml 文檔我命名為 loader_component_file.qml ,內(nèi)容如下:

[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????width:?320;??????height:?240;??????color:?"#EEEEEE";????????????Text?{??????????id:?coloredText;??????????anchors.horizontalCenter:?parent.horizontalCenter;??????????anchors.top:?parent.top;??????????anchors.topMargin:?4;??????????text:?"Hello?World!";??????????font.pixelSize:?32;??????}????????????Loader{??????????id:?redLoader;??????????width:?80;??????????height:?60;??????????focus:?true;??????????anchors.left:?parent.left;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????source:?"ColorPicker.qml";??????????KeyNavigation.right:?blueLoader;??????????KeyNavigation.tab:?blueLoader;????????????????????onLoaded:{??????????????item.color?=?"red";??????????????item.focus?=?true;??????????}????????????????????onFocusChanged:{????????????????item.focus?=?focus;??????????}??????}????????????Loader{??????????id:?blueLoader;??????????focus:?true;??????????anchors.left:?redLoader.right;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????source:?"ColorPicker.qml";??????????KeyNavigation.left:?redLoader;??????????KeyNavigation.tab:?redLoader;????????????????????onLoaded:{??????????????item.color?=?"blue";??????????}????????????????????onFocusChanged:{??????????????item.focus?=?focus;??????????}????????}????????Connections?{??????????target:?redLoader.item;??????????onColorPicked:{??????????????coloredText.color?=?clr;??????????????if(!redLoader.focus){??????????????????redLoader.focus?=?true;??????????????????blueLoader.focus?=?false;??????????????}??????????}??????}????????????Connections?{??????????target:?blueLoader.item;??????????onColorPicked:{??????????????coloredText.color?=?clr;??????????????if(!blueLoader.focus){??????????????????blueLoader.focus?=?true;??????????????????redLoader.focus?=?false;??????????????}??????????}??????}??}??
? ? 代碼有幾處改動:

? ? 一處是將 sourceComponent 修改為 source ,其值為 "ColorPicker.qml" 。

? ? 一處是兩個 Connections 對象,在 onColorPicked 信號處理器中,設(shè)置了 Loader 的焦點屬性,因為 只有 Loader 有焦點,它加載的 item 才會有焦點,如果你鼠標點擊某個顏色選擇組件而加載它的 Loader 沒有焦點,那么雖然顏色可以改變,但是焦點框出不來。

? ? 使用 Loader 加載定義在 qml 文檔中的組件,比直接使用組件名構(gòu)造對象要繁瑣得多,但如果你的應(yīng)用會根據(jù)特定的情景來決定某些界面元素是否顯示,這種方式也許可以滿足你。

利用 Loader 動態(tài)創(chuàng)建與銷毀組件

? ? 現(xiàn)在我們看看如何動態(tài)創(chuàng)建、銷毀組件。下面是 dynamic_component.qml :

[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????width:?320;??????height:?240;??????color:?"#EEEEEE";??????id:?rootItem;??????property?var?colorPickerShow?:?false;????????????Text?{??????????id:?coloredText;??????????anchors.horizontalCenter:?parent.horizontalCenter;??????????anchors.top:?parent.top;??????????anchors.topMargin:?4;??????????text:?"Hello?World!";??????????font.pixelSize:?32;??????}????????????Button?{??????????id:?ctrlButton;??????????text:?"Show";??????????anchors.left:?parent.left;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;????????????????????onClicked:{?????????????if(rootItem.colorPickerShow){?????????????????redLoader.source?=?"";?????????????????blueLoader.source?=?"";?????????????????rootItem.colorPickerShow?=?false;?????????????????ctrlButton.text?=?"Show";?????????????}else{?????????????????redLoader.source?=?"ColorPicker.qml";?????????????????redLoader.item.colorPicked.connect(onPickedRed);?????????????????blueLoader.source?=?"ColorPicker.qml";?????????????????blueLoader.item.colorPicked.connect(onPickedBlue);?????????????????redLoader.focus?=?true;?????????????????rootItem.colorPickerShow?=?true;?????????????????ctrlButton.text?=?"Hide";?????????????}??????????}??????}????????????Loader{??????????id:?redLoader;??????????anchors.left:?ctrlButton.right;??????????anchors.leftMargin:?4;??????????anchors.bottom:?ctrlButton.bottom;????????????????????KeyNavigation.right:?blueLoader;??????????KeyNavigation.tab:?blueLoader;????????????????????onLoaded:{??????????????if(item?!=?null){??????????????????item.color?=?"red";??????????????????item.focus?=?true;??????????????}??????????}????????????????????onFocusChanged:{????????????????if(item?!=?null){??????????????????item.focus?=?focus;??????????????}??????????}??????}????????????Loader{??????????id:?blueLoader;??????????anchors.left:?redLoader.right;??????????anchors.leftMargin:?4;??????????anchors.bottom:?redLoader.bottom;????????????KeyNavigation.left:?redLoader;??????????KeyNavigation.tab:?redLoader;????????????????????onLoaded:{??????????????if(item?!=?null){??????????????????item.color?=?"blue";??????????????}??????????}????????????????????onFocusChanged:{??????????????if(item?!=?null){??????????????????item.focus?=?focus;??????????????}??????????}????????}????????????function?onPickedBlue(clr){??????????coloredText.color?=?clr;??????????if(!blueLoader.focus){?????????????blueLoader.focus?=?true;?????????????redLoader.focus?=?false;??????????}??????}????????????function?onPickedRed(clr){??????????coloredText.color?=?clr;??????????if(!redLoader.focus){?????????????redLoader.focus?=?true;?????????????blueLoader.focus?=?false;??????????}??????????}??}??
? ? 這次我們在界面上放一個按鈕,通過按鈕來控制顏色選擇組件的創(chuàng)建與銷毀。啟動應(yīng)用時沒有創(chuàng)建顏色選擇組件,如圖 4 所示:


? ? ? ? ? ? 圖 4 動態(tài)創(chuàng)建組件初始效果

? ? 當你點擊 "Show" 按鍵,代碼通過設(shè)置 redLoader 和 blueLoader 的 source 來創(chuàng)建顏色選擇組件,連接顏色組件的 colorPicked 信號到相應(yīng)的方法,同時將改變按鈕文字,也改變 rootItem 維護的顏色組件是否顯示的標志位以便下次再點擊按鈕可以正常顯示。圖 5 是顏色選擇組件顯示后的效果圖:


? ? ? ? ? ? 圖 5 顏色組件創(chuàng)建后的效果


? ? 使用 Loader 控制組件的動態(tài)創(chuàng)建與銷毀,只是 Qt Quick 提供的動態(tài)維護對象的兩種方式中的一種。還有一種,是在 JavaScript 中動態(tài)創(chuàng)建 QML 對象。

在 JavaScript 中動態(tài)創(chuàng)建 QML 對象

? ? QML 支持在 JavaScript 中動態(tài)創(chuàng)建對象。這對于延遲對象的創(chuàng)建、縮短應(yīng)用的啟動時間都是有幫助的。同時這種機制也使得我們可以根據(jù)用戶的輸入或者某些事件來動態(tài)的將可見元素添加到應(yīng)用場景中。

? ? 在 JavaScript 中,有兩種方式可以動態(tài)地創(chuàng)建對象:

使用?Qt.createComponent() 動態(tài)地創(chuàng)建一個組件對象,然后使用 Component 的 createObject() 方法創(chuàng)建對象使用??Qt.createQmlObject() 從一個 QML 字符串直接創(chuàng)建一個對象

? ? 如果你在一個 qml 文件中定義了一個組件(比如我們的 ColorPicker ),而你想動態(tài)地創(chuàng)建它的實例,使用 Qt.createComponent() 是比較好的方式;而如果你的 QML 對象本身是在應(yīng)用運行時產(chǎn)生的,那 Qt.createQmlObject() 可能是比較好的選擇。

從組件文件動態(tài)創(chuàng)建 Component

? ? Qt 對象的 createComponent() 方法可以根據(jù) QML 文件動態(tài)的創(chuàng)建一個組件。一旦你擁有了組件對象,就可以調(diào)用它的 createObject() 方法創(chuàng)建一個組件的實例。下面是我們新的示例, qml 文件是 qt_create_component.qml :

[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????id:?rootItem;??????width:?360;??????height:?300;??????property?var?count:?0;??????property?Component?component:?null;????????????Text?{??????????id:?coloredText;??????????text:?"Hello?World!";??????????anchors.centerIn:?parent;??????????font.pixelSize:?24;??????}????????????function?changeTextColor(clr){??????????coloredText.color?=?clr;??????}????????????function?createColorPicker(clr){??????????if(rootItem.component?==?null){??????????????rootItem.component?=?Qt.createComponent("ColorPicker.qml");??????????}??????????var?colorPicker;??????????if(rootItem.component.status?==?Component.Ready)?{??????????????colorPicker?=?rootItem.component.createObject(rootItem,?{"color"?:?clr,?"x"?:?rootItem.count?*55,?"y"?:?10});??????????????colorPicker.colorPicked.connect(rootItem.changeTextColor);??????????}????????????????????rootItem.count++;??????}????????????Button?{??????????id:?add;??????????text:?"add";??????????anchors.left:?parent.left;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????onClicked:?{??????????????createColorPicker(Qt.rgba(Math.random(),?Math.random(),?Math.random(),?1));??????????}??????}??}??

? ? 圖 6 是示例啟動后的界面:


? ? ? ? ? ? 圖 6 qt create component 初始效果

? ? 圖 7 是我點擊了 6 次 "add" 按鈕后的效果:


? ? ? ? ? ? ? ? 圖 7 動態(tài)創(chuàng)建了顏色選擇組件

? ? 好啦,現(xiàn)在讓我們來看看代碼。

? ? 我在 qt_create_component.qml 中定義了?createColorPicker() 函數(shù),該函數(shù)的參數(shù)是顏色值,它根據(jù)顏色值來創(chuàng)建一個顏色選擇組件實例。首先它判斷 rootItem 的 component 屬性如果為 null ,就調(diào)用 Qt.createComponent() 創(chuàng)建一個 ColorPicker 組件,然后調(diào)用 Component.createObject() 創(chuàng)建一個顏色選擇組件實例。 createObject() 方法有兩個參數(shù),第一個參數(shù)用來指定創(chuàng)建出來的 item 的 parent ,第二個參數(shù)用來傳遞初始化參數(shù)給待創(chuàng)建的 item ,這些參數(shù)以 key - value 的形式保存在一個對象中。我在創(chuàng)建顏色組件實例時,傳遞顏色、 x 、 y 三個屬性給待創(chuàng)建的 item ,于是你看到了,那些色塊都在界面頂部。創(chuàng)建了顏色選擇組件實例,我調(diào)用 colorPicked 信號的 connect() 方法,連接 rootItem 的 changeTextColor 方法,以便用戶點擊色塊時改變 "Hello World!" ?文本的顏色。

? ? 再來看 "add" 按鈕,它的 onClicked 信號處理器,調(diào)用 Math 對象的隨機函數(shù) random() 和 Qt.rgba() ,隨機生成一個 Color 對象,傳遞給 createColorPicker() 方法來創(chuàng)建指定顏色的顏色選擇組件實例。

? ? 提一下,對于嵌入在 qml 文檔內(nèi)定義的 Component ,因為 Component 對象是現(xiàn)成的,可以略去 Qt.createComponent() 調(diào)用,直接使用 createObject() 方法創(chuàng)建組件實例。

? ? 代碼就這么簡單,解說到此為止?,F(xiàn)在讓我們看看怎么使用 Qt.createQmlObject() 來創(chuàng)建對象。

從 QML 字符串創(chuàng)建對象? ? 如果你的軟件,需要在運行過程中,根據(jù)應(yīng)用的狀態(tài)適時的生成用于描述對象的 QML 字符串,進而根據(jù)這個 QML 字符串創(chuàng)建對象,那么可以使用像下面這樣:[javascript]?view plain?copyvar?newObject?=?Qt.createQmlObject('import?QtQuick?2.0;?Rectangle?{color:?"red";?width:?20;?height:?20}',??????parentItem,?"dynamicSnippet1");??
? ? createQmlObject 的第一個參數(shù)是要創(chuàng)建對象的 QML 字符串,就像一個 QML 文檔一樣,你需要導(dǎo)入你用到的所有類型和模塊;第二個參數(shù)用于指定要創(chuàng)建的對象的父對象;第三個參數(shù),用于給新創(chuàng)建的對象關(guān)聯(lián)一個文件路徑,主要用于報告錯誤。

? ? 對于動態(tài)創(chuàng)建的對象,該如何銷毀呢?

銷毀動態(tài)創(chuàng)建的對象? ? 有些軟件,在不需要一個動態(tài)創(chuàng)建的 QML 對象時,僅僅是把它的 visible 屬性設(shè)置為 false 或者把 opactity 屬性設(shè)置為 0 ,而不是刪除這個對象。如果動態(tài)創(chuàng)建的對象很多,無用的對象都這么處理而不直接刪除,那會給軟件帶來比較大的性能問題,比如內(nèi)存占用增多,運行速度變慢等等。所以呢,動態(tài)創(chuàng)建的對象,不再使用時,最好把它刪除掉。? ? 我們這里說的動態(tài)創(chuàng)建的對象,特指使用 Qt.createComponent() 或 Qt.createQmlObject() 方法創(chuàng)建的對象, 使用 Loader 創(chuàng)建的對象,應(yīng)當通過將 source 設(shè)置為空串或?qū)?sourceComponent 設(shè)置為 undefined 觸發(fā) Loader 銷毀它們。? ? 要刪除一個對象,可以調(diào)用其 destroy() 方法。 destroy() 方法有一個可選參數(shù),指定延遲多少毫秒再刪除這個對象,其默認值為 0 。 destroy() 方法有點兒像 Qt C++ 中 QObject 的 deleteLater() 方法,即便你設(shè)定延遲為 0 去調(diào)用它,對象也并不會立即刪除,QML 引擎會在當前代碼塊執(zhí)行結(jié)束后的某個合適的時刻刪除它們。所以呢,即便你在一個對象內(nèi)部調(diào)用 destroy() 方法也是安全的。? ? 現(xiàn)在讓我我們再來一個實例,看看如何銷毀對象。新的 qml 文件命名為 delete_dynamic_object.qml ,從 qt_create_component.qml 拷貝而來,作了一點點修改。先看下:[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????id:?rootItem;??????width:?360;??????height:?300;??????property?var?count:?0;??????property?Component?component:?null;????????????Text?{??????????id:?coloredText;??????????text:?"Hello?World!";??????????anchors.centerIn:?parent;??????????font.pixelSize:?24;??????}????????????function?changeTextColor(clr){??????????coloredText.color?=?clr;??????}????????????function?createColorPicker(clr){??????????if(rootItem.component?==?null){??????????????rootItem.component?=?Qt.createComponent("ColorPicker.qml");??????????}??????????var?colorPicker;??????????if(rootItem.component.status?==?Component.Ready)?{??????????????colorPicker?=?rootItem.component.createObject(rootItem,?{"color"?:?clr,?"x"?:?rootItem.count?*55,?"y"?:?10});??????????????colorPicker.colorPicked.connect(rootItem.changeTextColor);??????????????//[1]?add?3?lines?to?delete?some?obejcts??????????????if(rootItem.count?%?2?==?1)?{??????????????????colorPicker.destroy(1000);??????????????}??????????}????????????????????rootItem.count++;??????}????????????Button?{??????????id:?add;??????????text:?"add";??????????anchors.left:?parent.left;??????????anchors.leftMargin:?4;??????????anchors.bottom:?parent.bottom;??????????anchors.bottomMargin:?4;??????????onClicked:?{??????????????createColorPicker(Qt.rgba(Math.random(),?Math.random(),?Math.random(),?1));??????????}??????}??}??
? ? 修改的部分我用注釋標注出來了:添加了三行代碼,新創(chuàng)建的顏色選擇組件實例,隔一個刪一個, destroy(1000) ?調(diào)用指示對象在 1 秒后刪除。? ? 圖 8 是運行后的效果圖:
? ? ? ? ? ? ? ? 圖 8 刪除動態(tài)創(chuàng)建的對象? ? 我還制作了一個演示刪除動態(tài)創(chuàng)建的對象的示例, qml 文件是 delete_dynamic_object2.qml ,我把點擊 "add" 按鈕創(chuàng)建的對象保存在一個數(shù)組中,當你點擊 "del" 按鈕時,刪除最后添加的那個顏色選擇組件實例。下面是代碼:[javascript]?view plain?copyimport?QtQuick?2.0??import?QtQuick.Controls?1.1????Rectangle?{??????id:?rootItem;??????width:?360;??????height:?300;??????property?var?count:?0;??????property?Component?component:?null;??????property?var?dynamicObjects:?new?Array();????????????Text?{??????????id:?colored
本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉