當(dāng)前位置:首頁 > 嵌入式 > 嵌入式軟件
[導(dǎo)讀] 編程示例使用Qt創(chuàng)建應(yīng)用程序是十分簡單的。考慮到你的使用習(xí)慣,我們編寫了兩套教程來實(shí)現(xiàn)兩個(gè)相似的應(yīng)用程序,但是使用了不同的方法。在開始之前,請(qǐng)確保你已經(jīng)下載了QtS

 編程示例

使用Qt創(chuàng)建應(yīng)用程序是十分簡單的??紤]到你的使用習(xí)慣,我們編寫了兩套教程來實(shí)現(xiàn)兩個(gè)相似的應(yīng)用程序,但是使用了

不同的方法。在開始之前,請(qǐng)確保你已經(jīng)下載了QtSDK的商業(yè)版本或者開源版本,并且你也已經(jīng)熟悉了Qt的開發(fā)工具。QtSDK

提供了QtCreator集成開發(fā)環(huán)境使得開發(fā)Qt的應(yīng)用程序十分簡單。

用戶界面的選擇

除了直觀上知道Qt是跨平臺(tái)的,提供了包括線程,網(wǎng)絡(luò)通信以及視頻回放和網(wǎng)絡(luò)攝像頭等的跨平臺(tái)抽象外,Qt提供了兩種

獨(dú)立的方法創(chuàng)建用戶界面。

QtQuick模塊為創(chuàng)建流暢的、活生生的用戶界面提供了一種標(biāo)記語言。這種方式適合那些需要?jiǎng)赢嬙氐慕缑?,以及?yīng)用程序

主要運(yùn)行在小屏幕和多點(diǎn)觸控的設(shè)備上的場景。

QtWidgets模塊針對(duì)傳統(tǒng)桌面提供了更多的支持,和目標(biāo)平臺(tái)做了更多的集成,無論目標(biāo)平臺(tái)是MacOSX,Windows,KDE還會(huì)Gnome。它是一個(gè)非常高效的基于C++的類庫,包含了很多常見的用戶界面組件,你可以非常容易的為這些已存在的組件

擴(kuò)展新的功能。

你選擇那個(gè)模塊來創(chuàng)建用戶界面取決于你想創(chuàng)建怎樣的應(yīng)用程序。其它的方法在余下的Qt庫中都是一樣的,所以你可以盡

可能的將應(yīng)用程序中邏輯處理的代碼寫得更加獨(dú)立一些。當(dāng)你熟悉了下面兩個(gè)示例,你可以再做決定選擇哪一個(gè)模塊來創(chuàng)建用

戶界面。對(duì)于更加詳細(xì)的信息,可以查看用戶界面信息。

教程

這里有兩個(gè)用于創(chuàng)建兩個(gè)相似應(yīng)用程序的例子。一個(gè)是使用QtQuick創(chuàng)建用戶界面,而另一個(gè)則是使用QtWidgets來創(chuàng)建用戶界面。

使用QtQuick開始編程

歡迎來到QML的世界。在這個(gè)示例中我們將會(huì)使用QML創(chuàng)建一個(gè)簡單的文本編輯器應(yīng)用程序。在閱讀完這個(gè)指南之后,

你應(yīng)該可以使用QML和QtC++開發(fā)自己的應(yīng)用程序。

QML構(gòu)建用戶界面

本應(yīng)用程序是一個(gè)簡單的文本編輯器,可以加載、保存和執(zhí)行一些文本的操作。這個(gè)指南將會(huì)包含兩個(gè)部分。第一部分將會(huì)

涉及到應(yīng)用程序的布局以及使用QML語言。在第二部分,我們將會(huì)使用QtC++實(shí)現(xiàn)文本的加載和保存。使用Qt的元對(duì)象系統(tǒng)我們

可以將C++的功能作為QML元素的屬性使用。使用QML和QtC++,我們可以將界面邏輯和應(yīng)用程序邏輯分離開。

 

 

最終的源代碼在examples/tutorials/gettingStartedQml目錄。你也許需要先編譯examples/tutprials/gettingStartedQml/filedialog目錄下的

C++插件。這一步會(huì)將C++插件放在QML能夠找到的目錄下。要啟動(dòng)這個(gè)應(yīng)用程序,僅僅需要使用qmlscene工具,將QML作為

參數(shù)傳遞給這個(gè)工具。C++的部分假設(shè)了閱讀者已經(jīng)掌握了基本的Qt編譯過程。

教程章節(jié):

定義按鈕和菜單

實(shí)現(xiàn)菜單欄

編譯文本編輯器

裝飾文本編輯器

使用QtC++擴(kuò)展QML

定義一個(gè)按鈕和菜單

基本組件——按鈕

我們以構(gòu)建一個(gè)按鈕開始我們的文本編輯器。在功能上,按鈕有一個(gè)鼠標(biāo)敏感區(qū)域和一個(gè)標(biāo)簽。當(dāng)用戶點(diǎn)擊按鈕的時(shí)候,

按鈕執(zhí)行一個(gè)動(dòng)作。

在QML中,最基本的可視化單元就是矩形(Rectangle)元素。矩形元素具有控制元素外觀和位置的屬性。

首先,導(dǎo)入QtQuick2.0允許qmlscene工具加載QML元素以便稍后使用。這一行代碼在所有的QML文件中都存在。需要注意

的是,我們導(dǎo)入Qt的模塊的時(shí)候也導(dǎo)入了版本號(hào)。

這個(gè)簡單的矩形有一個(gè)唯一的標(biāo)簽”simplebutton”,這就是id屬性。矩形元素的屬性是通過依次羅列屬性,中間以分號(hào)間隔,

然后就是屬性的值。在示例代碼中,”grey”顏色就綁定到了矩形的顏色屬性。類似地,我們也綁定了該矩形的高度和寬度。

Text元素是一個(gè)不可編輯的文本區(qū)域。我們給這個(gè)文本框命名為”buttonlabel”。我們通過將值綁定到”text”屬性來設(shè)置該文本

框的文字。這個(gè)文本框在矩形的中間,我們將文本框的”anchors”設(shè)置為其父親,也就是前面提到的simplebutton。Anchors也可以

綁定到其它元素的anchors,使得布局更加的簡單。

我們將這些代碼保存為SimpleButton.qml。使用這個(gè)文件的文件名作為參數(shù)調(diào)用qmlscene工具,將會(huì)出現(xiàn)如下的效果:

 

 

要實(shí)現(xiàn)按鈕的功能,我們可以使用QML的事件處理機(jī)制。QML的事件處理機(jī)制和Qt的信號(hào)-槽機(jī)制十分類似。信號(hào)被發(fā)射

然后關(guān)聯(lián)的槽函數(shù)被調(diào)用。

 

 

在我們的simplebutton矩形中,我們包含了一個(gè)MouseArea元素。MouseArea元素描述了可交互的區(qū)域,也就是鼠標(biāo)的移動(dòng)會(huì)

被檢測的區(qū)域。在這個(gè)例子中,我們將MouseArea的anchor設(shè)置為它的父親,也就是前面提到的simplebutton。Anchors.fill是獲取

指定屬性的一種語法表達(dá)方式。fill是屬性簇anchors中的一個(gè)特定屬性。QML使用了基于anchor的布局,元素可以anchor其它的元

素,創(chuàng)建健壯的布局。

當(dāng)鼠標(biāo)在MouseArea區(qū)域中移動(dòng)時(shí)MouseArea有許多事件處理者。其中的一個(gè)事件處理者就是onClicked,該事件處理會(huì)在允

許鼠標(biāo)點(diǎn)擊的區(qū)域中點(diǎn)擊鼠標(biāo)時(shí)候被調(diào)用,默認(rèn)是左鍵單擊。我們可以將一個(gè)動(dòng)作綁定到onClicked處理句柄。在我們的示例中

,當(dāng)鼠標(biāo)點(diǎn)擊時(shí),console.log()輸出文本。Console.log()函數(shù)是一個(gè)有用的調(diào)試輸出函數(shù)。

如下的代碼足夠完成顯示按鈕且在鼠標(biāo)單擊的時(shí)候輸出文本。

 

 

一個(gè)功能齊全的按鈕在Button.qml中。示例代碼中有部分被省略了,因?yàn)檫@些代碼要么在之前介紹過了,要么就是與本章

介紹的內(nèi)容不是很相關(guān)。

我們可以使用屬性類型名稱的語法來自定義屬性。在示例代碼中,buttonColor屬性就是自定義的并且被賦值為”lightblue”。buttonColor在后面就被使用到了,用來根據(jù)不同操作填充不同的顏色。值得注意的是,屬性的賦值使用的是”=”,

而屬性的值綁定使用的則是”:”。自定義的屬性使得內(nèi)部元素的可見范圍可以超出矩形的范圍。QML基本類型有int,string,real和variant。通過綁定onEntered和onExited信號(hào)處理到顏色上,當(dāng)鼠標(biāo)停留在按鈕之上,按鈕的邊框?qū)?huì)變?yōu)辄S

顏色,并且在鼠標(biāo)離開按鈕的時(shí)候恢復(fù)為原來的顏色。

我們通過將signal關(guān)鍵字放在信號(hào)名稱之前,自定義了一個(gè)buttonClick()信號(hào)在Button.qml中,所有的信號(hào)的處理者都是自動(dòng)

被創(chuàng)建的,這是通過簡單在信號(hào)的名字前面加上”on”這個(gè)單詞。顯然,onButtonClick就是buttonClick的處理者。onButtonClick會(huì)

被賦予一些動(dòng)作。在我們的按鈕示例中,onClicked鼠標(biāo)處理者將會(huì)簡單的調(diào)用onButtonClick,功能就是現(xiàn)實(shí)一個(gè)文本。

onButtonClick使得外部對(duì)象可以十分輕易的獲取按鈕的鼠標(biāo)區(qū)域。例如:將設(shè)有許多的元素,這些元素?fù)碛性S多的MouseArea,

那么一個(gè)buttonClick信號(hào)可以在許多的MouseArea做出區(qū)分,使得分別處理幾個(gè)MouseArea更加簡單。

我們現(xiàn)在已經(jīng)具備了基本的知識(shí):在QML中實(shí)現(xiàn)基本元素并可以處理鼠標(biāo)移動(dòng)事件。我們?cè)谝粋€(gè)巨型中創(chuàng)建一個(gè)文本框,自定義了屬性,針對(duì)鼠標(biāo)移動(dòng)實(shí)現(xiàn)了相應(yīng)的處理。在元素中創(chuàng)建元素的思想貫穿著整個(gè)示例。

現(xiàn)在該按鈕還沒有什么用,除非他作為組件可以執(zhí)行一些動(dòng)作。在下面一節(jié),我們將會(huì)快速的創(chuàng)建一個(gè)菜單,包含幾個(gè)這樣的按鈕。

 

 

創(chuàng)建一個(gè)菜單頁

在這一階段,我們將會(huì)介紹如何在一個(gè)單獨(dú)的QML文件中創(chuàng)建元素并指定動(dòng)作。在這一節(jié),我們將會(huì)介紹如何導(dǎo)入QML元素

以及如何使用已經(jīng)存在的組件構(gòu)建新的組件。

菜單顯示了一個(gè)列表內(nèi)容,每一個(gè)元素都用執(zhí)行一個(gè)特殊動(dòng)作的功能。在QML中,我們可以使用幾種方式創(chuàng)建菜單。首先我們會(huì)創(chuàng)建一個(gè)包含按鈕的菜單,每一個(gè)按鈕執(zhí)行不同的動(dòng)作。菜單的代碼在文件FileMenu.qml中。

 

 

上面的語法展示了如何導(dǎo)入關(guān)鍵字。這里需要使用JavaScript文件,或者使用不在同一目錄下的QML文件。因?yàn)锽utton.qml文件和FileMenu.qml文件在同一個(gè)目錄下,因此我們無需導(dǎo)入Button.qml文件就可以使用它。我們可以直接通過聲明Button()創(chuàng)建按鈕,

類似Rectangle的聲明。

 

 

在FileMenu.qml文件中聲明了三個(gè)Button元素。它們都聲明在一個(gè)Row元素內(nèi)。該元素將其子元素水平放置。Button是在Button.qml文件中聲明的,這種用法和上一節(jié)的用法一致。在新創(chuàng)建的button中,我們可以將其屬性綁定為新值,覆蓋它們?cè)贐utton.qml中綁定的默認(rèn)值。exitButton按鈕在被按下的時(shí)候整個(gè)應(yīng)用程序就會(huì)退出。值得注意的是:在Button.qml中定義的信號(hào)onButtonClick將會(huì)在FileMenu.qml中被調(diào)用,除了exitButton的onButtonClick事件處理者。

 

 

Row是在一個(gè)Rectangle中聲明的,創(chuàng)建了一個(gè)用于防止按鈕的矩形容器。這個(gè)矩形創(chuàng)建了一個(gè)間接的方式用于組織在一個(gè)菜單中

的按鈕行。編輯菜單的聲明和之前菜單聲明十分類似。菜單中的按鈕的標(biāo)簽為:Copy,Paste和SelectAll。

 

 

實(shí)現(xiàn)一個(gè)菜單欄

我們的文本編輯程序需要使用菜單欄來顯示菜單。菜單欄將會(huì)切換到不同的菜單,并且用戶可以選擇那些菜單可以顯示。

菜單的切換意味著菜單需要更多的結(jié)構(gòu)而不僅僅是將它們成行的顯示出來。QML使用模型和視圖來組織數(shù)據(jù)以及顯示結(jié)構(gòu)化的

數(shù)據(jù)。

使用數(shù)據(jù)模型和視圖

QML有不同的數(shù)據(jù)視圖來顯示數(shù)據(jù)模型。我們的菜單欄會(huì)將菜單以列表的方式顯示出來,也包含一個(gè)用于顯示菜單名的頭部。菜單列表是在VisualItemModel中聲明的。VisualItemModel元素包含那些已經(jīng)具有視圖的元素,例如矩形以及導(dǎo)入的UI元素。其它的

模型類型,例如ListModel元素需要一個(gè)代理來顯示它的數(shù)據(jù)。

我們?cè)趍enuListModel中聲明兩個(gè)可視化元素:FileMenu和EditMenu。我定制了這兩個(gè)菜單并且使用ListView來顯示它們。MenuBar.qml文件包含了QML聲明,一個(gè)簡單的編輯菜單定義在EditMenu.qml文件中:

ListView元素將會(huì)依照代理來顯示模型。代理可能聲明模型元素以Row元素顯示,也可能以網(wǎng)格的方式顯示。我們的menuListModel已經(jīng)包含了可視化元素,因此,我們不需要聲明代理。

 

 

另外,ListView繼承自Flickable,使得列表可以響應(yīng)鼠標(biāo)的拖拽以及其它的一些手勢。上面代碼的最后部分設(shè)置了Flickable

屬性用于創(chuàng)建我們想要的滑動(dòng)操作。特別是highlightMoveDuration屬性改變滑動(dòng)轉(zhuǎn)換的周期。一個(gè)highlightMoveDuration使得菜單

間的切換更加緩慢。

ListView通過一個(gè)索引(index)來維護(hù)模型元素,并且模型中的每一個(gè)可視化元素都可以通過索引來獲取,索引的順序是根據(jù)

元素被聲明的順序定義的。改變currentIndex的值將會(huì)導(dǎo)ListView中高亮的元素改變。我們菜單欄的頭部證明了這種效果。這里有

兩個(gè)按鈕,點(diǎn)擊任何一個(gè)都會(huì)切換當(dāng)前的菜單。當(dāng)點(diǎn)擊fileButton的時(shí)候,菜單切換到FileMenu,并且索引變?yōu)?,因?yàn)镕ileMenu在menuListModel中是最先聲明的,editButton類似。labelList矩形有一個(gè)取值為1的z變量,這意味著它是在菜單欄的上

面顯示(空間坐標(biāo)系)。z值較大的元素始終在z值較小的元素的上面顯示。默認(rèn)的z值是0。

 

 

目前創(chuàng)建的菜單欄僅僅具有菜單切換的效果,通過點(diǎn)擊頭部的兩個(gè)按鈕來進(jìn)行切換:

 

 

構(gòu)建文本編輯器

聲明一個(gè)文本區(qū)域(TextArea)

如果我們的文本編輯器不具有一個(gè)可編輯的區(qū)域,那么他就不能被稱為文本編輯器。QML的TextEdit元素允許聲明一個(gè)

多行編輯的文本區(qū)域。TextEdit元素和Text元素是有區(qū)別的,后者不允許用戶對(duì)文本進(jìn)行編輯。

 

 

上面設(shè)置了編輯器的前景色屬性和環(huán)繞文字的模式。TextEdit區(qū)域是包含在一個(gè)flickable的區(qū)域中的,這確保了當(dāng)文字光標(biāo)

了當(dāng)前的顯示區(qū)域,那么文本內(nèi)容會(huì)自動(dòng)滾動(dòng)。函數(shù)ensureVisible()將會(huì)檢查鼠標(biāo)是否處在可見區(qū)域的外面并且根據(jù)檢查的結(jié)果

移動(dòng)滾動(dòng)文本區(qū)域。QML使用JavaScript語法作為其腳本,正如前面提到的,JavaScript可以導(dǎo)入并且在QML中使用。

 

 

為文本編輯器組裝組件

我們現(xiàn)在已經(jīng)準(zhǔn)備好了使用QML為我們的文本編輯器創(chuàng)建布局。文本編輯器包含兩個(gè)組件,已經(jīng)創(chuàng)建的菜單欄和文本區(qū)域。QML允許我們重用這些組件,因此我們可以通過導(dǎo)入組件以及在必要的時(shí)候做一些定制來簡化我們的代碼。我們的文本

編輯器將窗口分為兩個(gè)部分:屏幕的1/3用來顯示菜單欄,另外的2/3用來顯示文本區(qū)域。菜單欄在其他的元素上面顯示(空間坐標(biāo)系)。

 

 

通過導(dǎo)入可重用的組件,我們的文本編輯器的代碼看起來更加簡單了。我們可以定制自己的主應(yīng)用程序而不必?fù)?dān)心那些已經(jīng)

指定動(dòng)作的屬性。使用這種方法,應(yīng)用程序的布局和UI組件可以更加簡單的被創(chuàng)建。

 

 

裝飾文本編輯器

實(shí)現(xiàn)一個(gè)繪圖的接口

我們的文本編輯器看起來十分的簡單,因此我們需要裝飾一下。使用QML,我們可以為我們的文本編輯器定義轉(zhuǎn)換和動(dòng)畫。

我們的菜單欄占據(jù)1/3的屏幕,因此只在我們需要的時(shí)候才顯示它這個(gè)功能將會(huì)十分有用。

我添加了一個(gè)繪畫的接口,在我們單擊的時(shí)候,該接口將會(huì)收起或者展開菜單欄。在我們的實(shí)現(xiàn)中,我們使用了一個(gè)十分小

的矩形用于鼠標(biāo)點(diǎn)擊。繪畫接口和應(yīng)用程序都有兩種狀態(tài):繪畫接口是打開的和繪畫接口是關(guān)閉的。繪畫(drawer)元素是一個(gè)矩形,但是它的高度很小。這里有一個(gè)內(nèi)嵌在繪畫元素中間的Image元素,用于展示一個(gè)箭頭圖標(biāo)。繪畫元素將會(huì)通過screen標(biāo)簽賦予整個(gè)

應(yīng)用程序一個(gè)狀態(tài),無論用戶在什么時(shí)候點(diǎn)擊鼠標(biāo)區(qū)域

 

 

一個(gè)狀態(tài)僅僅是定義在State元素內(nèi)部的一系列配置的集合。我們可以列舉一系列的狀態(tài)通過綁定到states屬性。在我們的

應(yīng)用程序中,兩種狀態(tài)分別被稱為DRAWER_CLOSED和DRAWER_OPEN。元素的配置都是在PropertyChanges中聲明的。在DRAWER_OPEN狀態(tài)中,有四個(gè)元素將會(huì)被改變屬性。第一個(gè)目標(biāo),menubar將會(huì)改變自己的y屬性為0。類似的textArea在DRAWER_OPEN狀態(tài)中將會(huì)降低到一個(gè)新的位置。

 

 

狀態(tài)的轉(zhuǎn)變是突兀的并且是需要做平滑轉(zhuǎn)換的。在狀態(tài)之間的轉(zhuǎn)換是通過Transition元素定義的,定義好了之后可以綁定到

元素的transitions屬性。我們的文本編輯器有一個(gè)狀態(tài)轉(zhuǎn)換器。我們的文本編輯器需要在DRAWER_OPEN和DRAWER_CLOSE

兩種狀態(tài)之間轉(zhuǎn)換。重要的是,轉(zhuǎn)換器需要一個(gè)from狀態(tài)和一個(gè)to狀態(tài),我們可以使用*號(hào)通配符將該轉(zhuǎn)換器應(yīng)用于所有的狀態(tài)

轉(zhuǎn)換。

在狀態(tài)的轉(zhuǎn)換過程中,我們可以為屬性的變化指定動(dòng)畫。我們的menuBar位置在y:0到y(tǒng):-partition之前轉(zhuǎn)換,我們可以使用NumberAnimation元素使得這個(gè)轉(zhuǎn)換過程更生動(dòng)。我們聲明了目標(biāo)屬性將會(huì)動(dòng)畫一定時(shí)間,并且使用特定的曲線。一個(gè)曲線

控制著動(dòng)畫的轉(zhuǎn)換以及狀態(tài)轉(zhuǎn)換間的動(dòng)作。我們選擇的特定曲線是Easing.OutQuint,該曲線在接近終點(diǎn)的時(shí)候運(yùn)動(dòng)速度變慢。

可以看看有關(guān)QML動(dòng)畫的內(nèi)容。

 

 

另一種方式實(shí)現(xiàn)屬性變化時(shí)候的動(dòng)畫效果就是聲明一個(gè)Behavior元素。一個(gè)轉(zhuǎn)換器僅僅在狀態(tài)改變的時(shí)候工作,然而Behavior

可以在一般屬性發(fā)生改變的時(shí)候工作。在文本編輯器中,當(dāng)箭頭的旋轉(zhuǎn)屬性改變時(shí),箭頭有一個(gè)NumberAnimation的動(dòng)畫。

 

 

回到我們對(duì)于組件的狀態(tài)和動(dòng)畫知識(shí),我們可以提高我們組件的表現(xiàn)力。在Button.qml中,在按鈕被單擊的時(shí)候,我們可以

添加顏色(color)和比例(scale)屬性改變。顏色的動(dòng)畫使用的是ColorAnimation元素?cái)?shù)量的動(dòng)畫使用的是NumberAnimation。下面使

用的”onpropertyName”的語法形式對(duì)于目標(biāo)是單個(gè)屬性而言是十分有幫助的。

 

 

另外,我們可以通過使用顏色效果,例如:光柵效果等來增強(qiáng)QML組件的表現(xiàn)力。聲明一個(gè)Gradient元素將會(huì)覆蓋該元素的color屬性。你可以在gradient中使用GradiendStop元素聲明一種顏色。梯度(gradient)屬性使用的是比例值,介于0.0和1.0之間。

 

 

這個(gè)梯度值是被菜單欄使用的。最初的顏色是0.0,最后的則是1.0.

接下來怎么做

我們已經(jīng)完成了一個(gè)簡易的文本編輯器的界面。接下來我們的UI界面已經(jīng)完成,那么我們就可以使用Qt和C++來完成程序的邏輯部分。QML最為一個(gè)不錯(cuò)的原型工具,將應(yīng)用程序的邏輯部分和UI設(shè)計(jì)隔離開。

 

 

使用Qt Cpp擴(kuò)展QML

現(xiàn)在,我們已經(jīng)有了文本編輯框的布局,我們現(xiàn)在就使用C++實(shí)現(xiàn)文本編輯框的功能部分。使用QML和C++允許我們使用Qt創(chuàng)建

應(yīng)用程序的邏輯部分。我們可以使用Qt的Quick類在C++應(yīng)用程序中創(chuàng)建QML上下文,并且使用QQuickView顯示QML元素??蛇x的,我們也可以將C++代碼導(dǎo)出為一個(gè)qmlscene工具可以讀取的插件。在本示例中,我們將會(huì)使用C++實(shí)現(xiàn)加載和保存文本的功能,并且將C++代碼導(dǎo)出為一個(gè)插件。在這種方式下,我們僅僅需要直接加載QML文件,而不是運(yùn)行可執(zhí)行程序。

導(dǎo)出C++類到QML

我們使用Qt和C++實(shí)現(xiàn)加載和保存文本的功能,通過注冊(cè)C++的類和方法都可以在QML中被調(diào)用。C++類需要被編譯為Qt插

件,并且QML文件需要知道這個(gè)插件所處目錄。

對(duì)于我們的文本編輯器程序來說,我們需要?jiǎng)?chuàng)建如下的內(nèi)容:

Directory類,該類用于處理與目錄相關(guān)的操作;

File類,該類繼承自QObject,列出一個(gè)目錄下的所有文件;

插件類,該類將會(huì)注冊(cè)到QML上下文中;

Qt工程文件,使得這個(gè)Qt工程被編譯成插件;

一個(gè)qmldir文件,用于告訴qmlscene工具插件類所處的目錄。

編譯Qt插件

要編譯一個(gè)插件,我們需要將下面的內(nèi)容放置到Qt工程文件中。首先是必須添加到Qt工程文件中的源文件,頭文件以及Qt模塊。所有的C++代碼和工程文件都在filedialog目錄下:

 

 

特別需要注意的是,我們將qml模塊也連接到該工程中,并且配置為插件模式,使用lib模板。我們將編譯生成的插件放置在

上一層的plugins目錄下。

注冊(cè)一個(gè)類到QML中

 

 

我們需要使用Q_PLUGIN_METADATA宏來導(dǎo)出插件。注意,在我們的dialogPlugin.h文件中,我們將Q_OBJECT宏放置在我們

類的最上面。因?yàn)槲覀冃枰獙?duì)工程文件運(yùn)行qmake來產(chǎn)生必要的元對(duì)象代碼。

我們的插件類:DialogPlugin是QQmlExtensionPlugin的一個(gè)子類。我們需要實(shí)現(xiàn)繼承的方法:registerTypes()。dialogPlugin.cpp文

件內(nèi)容如下:

 

 

registerTypes()方法將我們的File和Directory類注冊(cè)到QML中。該方法需要類的名稱作為它的模板,一個(gè)主版本號(hào),一個(gè)次版本

號(hào)以及類名。

在C++類中創(chuàng)建QML屬性

我們可以使用C++和Qt的元對(duì)象系統(tǒng)來創(chuàng)建QML元素和屬性。我們可以使用信號(hào)-槽機(jī)制實(shí)現(xiàn)屬性,使得Qt可以識(shí)別這些屬性。然后,這些屬性就可以在QML中使用了。

針對(duì)我們的文本編輯器應(yīng)用,我們需要加載和保存文本。典型地,這些特性需要包含一個(gè)文件對(duì)話框。幸運(yùn)地是我們可以使用QDir、QFile和QTextStream來實(shí)現(xiàn)目錄的讀取以及輸入輸出流。

 

 

Directory類使用了Qt的元對(duì)象系統(tǒng)來注冊(cè)一些屬性以便完成文件處理。Directory類將會(huì)被作為一個(gè)插件導(dǎo)出,并且在QML中作為Directory元素使用。每一個(gè)使用Q_PROPERTY宏定義的屬性都是一個(gè)QML屬性。

Q_PROPERTY定義一個(gè)讀和寫的屬性就好比是元對(duì)象系統(tǒng)中讀和寫函數(shù)一樣。例如:filename屬性,是QString類型,可使用filename()方法讀取,使用setFilename()設(shè)置。另外,這里有一個(gè)信號(hào)關(guān)聯(lián)到了filename屬性:filenameChanged(),當(dāng)filename屬性

改變的時(shí)候就會(huì)發(fā)射這個(gè)信號(hào)。讀和寫函數(shù)在頭文件中是以public關(guān)鍵字聲明的。

類似的,我們也聲明了其它一些將會(huì)使用到的屬性。filesCount屬性表面一個(gè)目錄下的文件數(shù)。Filename屬性被設(shè)置為當(dāng)前選

中的文件的文件名,并且加載/保存文件的內(nèi)容都存放在屬性fileContent中。

 

 

Files列表屬性是在該目錄下過濾后剩下的文件列表。Directory類實(shí)現(xiàn)了過濾掉非法的文本文件,僅僅以”.txt”結(jié)尾的文件才是

合法的。Qlists可以通過在C++中聲明為QQmlListProperty屬性在QML文件中使用。模板對(duì)象都需要繼承自QObject,因此File類也

需要從QObject集成。在Directory類中,F(xiàn)ile對(duì)象列表保存在一個(gè)名為m_fileList的QList中。

 

 

這些屬性可以在QML中作為Directory元素的屬性使用。需要注意的是,我們不需要再C++代碼中創(chuàng)建一個(gè)表示標(biāo)簽的”id”屬性。

 

 

因?yàn)镼ML使用了JavaScript的語法和結(jié)構(gòu),因此我們可以在文件列表中迭代并獲取其屬性。要獲取第一個(gè)文件的名字屬性,

我們可以使用”files[0].name”。

普通的C++函數(shù)也可以在QML中使用。文件加載和保存函數(shù)使用C++代碼實(shí)現(xiàn),并且使用Q_INVOKABLE宏聲明??蛇x的

是,我們可以將這些函數(shù)作為槽函數(shù)聲明,然后這些函數(shù)也可以在QML中使用。

 

 

Directory類童謠需要在目錄內(nèi)容發(fā)生改變的時(shí)候通知其它的對(duì)象。這個(gè)特性可以使用信號(hào)實(shí)現(xiàn)。在前面已經(jīng)提到過,QML

信號(hào)有一個(gè)以on開頭的信號(hào)處理器。這里我們將信號(hào)命名為directoryChanged,在目錄被刷新的時(shí)候該信號(hào)被發(fā)射。目錄刷新僅

僅是再次加載目錄內(nèi)容,并且更新合法的文件列表。QML元素可以通過連接到onDirectoryChanged信號(hào)處理上得到目錄被改變

的通知。

List屬性需要繼續(xù)被討論。這是因?yàn)閘ist屬性使用回調(diào)函數(shù)訪問和修改list的內(nèi)容。List屬性的類型是QQmlListProperty。無

論在什么時(shí)候訪問列表,訪問器(accessorfunction)都應(yīng)該返回一個(gè)QQmlListProperty。模板類型File,需要繼承自QObject。因

此要構(gòu)造QQmlListProperty屬性,我們需要將列表的訪問器和修改器的函數(shù)指針作為參數(shù)傳遞給構(gòu)造器。同樣我們需要一個(gè)指向

File列表的QList指針。

 

 

構(gòu)造器將指針傳遞給追加列表的函數(shù),計(jì)算列表大小的函數(shù),使用索引(index)獲取條目的函數(shù)以及清空列表的函數(shù)。至于追加

列表的函數(shù)是必須的。需要注意的是:函數(shù)指針必須和AppendFunction、CountFunction、AtFunction以及ClearFunction相匹配。

 

 

為了簡化文件對(duì)話框,Directory類實(shí)現(xiàn)了過濾掉非法的文本文件(不以”.txt”結(jié)尾的文件)。如果一個(gè)文件不是以”.txt”結(jié)尾,那么

在它在文件對(duì)話框中就是不可見的。同樣,我們的實(shí)現(xiàn)也確保了文件的保存是以”.txt”結(jié)尾的。Directory類使用QTextStream類讀取

文件并將數(shù)據(jù)寫到文件中的。

使用我們的Directory元素,我們可以將文件組織為列表,我們可以知道目錄下有多少文件,可以獲取文件的名稱和內(nèi)容,并且

在目錄內(nèi)容改變的時(shí)候得到通知。

要編譯這個(gè)插件,我們需要在filedialog.pro文件上運(yùn)行qmake命令,然后運(yùn)行make命令來編譯并將插件拷貝到plugins目錄。

在QML中導(dǎo)入插件

Qmlscene工具將與應(yīng)用程序同一目錄下的文件直接導(dǎo)入。我們也可以通過創(chuàng)建一個(gè)qmldir文件,包含我們需要導(dǎo)入的QML文件

的位置。Qmldir文件也可以存儲(chǔ)插件以及其它資源的位置。

 

 

我們剛剛創(chuàng)建的插件是FileDialog,這是在工程文件的TARGET域指定的。編譯后的插件存放在plugins目錄下。

將FileDialog集成到FileMenu

我們的FileMenu需要顯示一個(gè)FileDialog元素,F(xiàn)ileDialog元素包含了一個(gè)目錄下文件的列表,允許用戶通過在列表中點(diǎn)擊來選

擇文件。我們同樣需要指定save,load,new三個(gè)按鈕來獲取這些動(dòng)作。FileMenu包含了一個(gè)可編輯的文本輸入框,允許用戶通過鍵盤

輸入文件名。

Directory元素在FileMenu.qml文件中被使用到,并且它通知FileDialog元素目錄的內(nèi)容得到了更新。這個(gè)通知是在信號(hào)處理者onDirectoryChanged中處理的。

 

 

為了繼續(xù)保持我們的應(yīng)用程序簡單,文件對(duì)話框?qū)⒉粫?huì)顯示任何非法文件。

 

 

FileDialog元素將會(huì)通過讀取files列表屬性來展示目錄的內(nèi)容。這些文件將會(huì)作為GridView元素的模型,GridView將通過代理

將數(shù)據(jù)元素以網(wǎng)格的形式顯示出來。代理主要用于處理模型的顯示,我們的文件對(duì)話框僅僅是創(chuàng)建文字處于中心的網(wǎng)格。點(diǎn)擊一

個(gè)文件名將會(huì)導(dǎo)致一個(gè)文件名高亮。當(dāng)notifyRefresh信號(hào)被發(fā)射,F(xiàn)ileDialog對(duì)話框就會(huì)被通知重新加載目錄的內(nèi)容。

 

 

現(xiàn)在我們的FileMenu可以連接到相應(yīng)的動(dòng)作上。saveButton將會(huì)把TextEdit上的文本轉(zhuǎn)化為目錄的fileContent屬性,然后從文本

輸入框中獲取文件的名稱,該按鈕會(huì)調(diào)用saveFile()函數(shù)保存文件。loadButton以類似的過程執(zhí)行。New按鈕將會(huì)清空TextEdit的內(nèi)容。

EditMenu下的按鈕會(huì)將copy,paste和selectall這些函數(shù)與TextEdit連接起來。

 

 

完成文本編輯器

 

 

該應(yīng)用程序是一個(gè)簡單的文本編輯器,可以加載和保存文件,并執(zhí)行簡單的操作:剪切、復(fù)制以及全選等功能。

運(yùn)行文本編輯器

在運(yùn)行文本編輯器之前,我們需要將C++代碼編譯為插件。要編譯C++代碼,我們進(jìn)入filedialog目錄,運(yùn)行qmake命令,然后

使用make或者nmake編譯,這取決于你的平臺(tái)。接著運(yùn)行qmlscene打開texteditor.qml文件即可。

源代碼在examples/tutorials/gettingStartedQml目錄下。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

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

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

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

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

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

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

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

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

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

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

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

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

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

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

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(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)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動(dòng)力")與長三角投資(上海)有限...

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