1、概述
ESM6802是英創(chuàng)公司推出的基于Freescale i.MX6DL雙核處理器(ARM Cortex-A9,主頻1GHz)的高性能工控主板,imx6dl內(nèi)部帶有硬件3D、2D圖像處理模塊,能夠?qū)D像界面繪制進(jìn)行硬件加速,使得應(yīng)用程序顯示更加快速流暢。ESM6802支持Qt 5.8版本,支持使用QML進(jìn)行界面開(kāi)發(fā),而且能夠利用硬件圖像加速處理模塊優(yōu)化QML構(gòu)建的圖像界面的渲染。本文將會(huì)簡(jiǎn)單介紹一下QML的基礎(chǔ)知識(shí),給客戶提供一種新的界面的開(kāi)發(fā)方案。
QML是Qt提供的一種描述性的腳本語(yǔ)言,類似于CSS(Cascading Style Sheets),可以在腳本里創(chuàng)建圖形對(duì)象,并且支持各種圖形特效,以及狀態(tài)機(jī)等,同時(shí)又能跟Qt寫的C++代碼進(jìn)行方便的交互,使用起來(lái)非常方便。采用QML加插件的方式主要是為了將界面設(shè)計(jì)與程序邏輯解耦,一般的系統(tǒng)開(kāi)發(fā)中界面設(shè)計(jì)的變動(dòng)往往多于后臺(tái)邏輯,因此采用QML加插件的方式將界面設(shè)計(jì)與邏輯分離有利于開(kāi)發(fā)人員的分工,加速產(chǎn)品迭代速度,降低后期維護(hù)成本。而且QML解釋性語(yǔ)言的特性使得其語(yǔ)法更加簡(jiǎn)單,可以將界面設(shè)計(jì)部分交給專業(yè)的設(shè)計(jì)人員開(kāi)發(fā),而不要求設(shè)計(jì)人員會(huì)c++等編程語(yǔ)言。Qt底層對(duì)QML做了優(yōu)化,將會(huì)優(yōu)先使用硬件圖形加速器進(jìn)行界面的渲染,也針對(duì)觸摸屏應(yīng)用做了優(yōu)化,使用QML能夠更簡(jiǎn)單快捷的搭建流暢、優(yōu)美的界面。QML也支持嵌入Javascript處理邏輯,但是底層邏輯處理使用Qt C++編寫插件,能夠更好的控制數(shù)據(jù)結(jié)構(gòu),數(shù)據(jù)處理也更加高效,Qt提供了多種方式將C++數(shù)據(jù)類型導(dǎo)入QML腳本中,更多詳細(xì)資料可以查看Qt官方的文檔,本文將簡(jiǎn)單介紹一下QML語(yǔ)言的語(yǔ)法以展示QML相對(duì)于以往的Qt C++界面編程的區(qū)別,文中所有代碼均在ESM6802 Linux上運(yùn)行測(cè)試過(guò)了,有需要的客戶可以向我們索取,QML文件是腳本文件,不需要編譯,可以使用/usr/bin/qt5/qmlscene程序直接打開(kāi)QML腳本文件查看效果。
2、QML基礎(chǔ)介紹
QML將界面分解為一個(gè)一個(gè)小的元素,通過(guò)使用QML描述各元素的排列以及對(duì)特定事件的響應(yīng)來(lái)搭建一個(gè)動(dòng)態(tài)的界面。QML中的元素是以層級(jí)的形式進(jìn)行描述的,子元素繼承父元素的坐標(biāo)系統(tǒng),子元素的坐標(biāo)以父元素作為參考,父元素的左上角為子元素的坐標(biāo)原點(diǎn),子元素中可以以parent關(guān)鍵字引用父元素。
在一個(gè)QML文件中,每個(gè)元素都可以設(shè)定唯一的id,在其他元素中可以引用id來(lái)更改此元素的屬性等。QML提供一系列內(nèi)置的元素類型供開(kāi)發(fā)中快速搭建界面,包括最常用的Rectangle、Image、Text、MouseArea、Item等。元素都有自己內(nèi)置的屬性,比如之前介紹的id,以及用于指定坐標(biāo)的x、y,和width、height等,同時(shí)也支持使用property關(guān)鍵字自定義屬性。一個(gè)簡(jiǎn)單的QML文件如下:
import QtQuick 2.0 Rectangle { width: 100 height: 100 color: "red" } |
這個(gè)QML文件將會(huì)展示一個(gè)紅色的正方形,如下圖:
在上面的例子中為Rectangle增加radius屬性的設(shè)置就可以得到圓角長(zhǎng)方形:
Rectangle { width: 100 height: 100 color: "red" radius: 10 } |
使用Rectangle就可以構(gòu)建出消息展示框和按鈕等大部分的界面元素了,而Text類型可以用于在Rectangle中增加文字信息,Image可以加載圖片,MouseArea提供鼠標(biāo)/觸摸屏事件,組合使用這幾個(gè)元素就能夠快速的搭建基本的交互界面了。
當(dāng)然現(xiàn)實(shí)開(kāi)發(fā)中由于需要展示的數(shù)據(jù)往往會(huì)以數(shù)組等更復(fù)雜形式進(jìn)行管理,他們具有相同的屬性,需要展示的外形效果(背景、對(duì)事件的相應(yīng))是一樣的,而每個(gè)元素的需要展示的內(nèi)容不一樣,這時(shí)就可以使用Row、Column、ListView、GridView等更復(fù)雜的元素。這類元素的設(shè)計(jì)理念是將數(shù)據(jù)與展現(xiàn)效果分開(kāi),數(shù)據(jù)用model來(lái)存放,而展示效果用view來(lái)描述,model和view通過(guò)delegate聯(lián)系起來(lái),一個(gè)簡(jiǎn)單的ListView的用法示例如下:
Background { width: 480 height: 80 ListView { anchors.fill: parent anchors.margins: 20 spacing: 4 clip: true model: 100 orientation: ListView.Horizontal delegate: numberDelegate } Component { id: numberDelegate GreenBox { width: 40 height: 40 text: index } } |
上面中的GreenBox是使用Rectangle元素和Text元素構(gòu)建的長(zhǎng)方形,上面的代碼顯示效果如下:
QML也內(nèi)置了一些類型來(lái)描述顯示元素的轉(zhuǎn)變、動(dòng)畫效果,例如PropertyAnimation、NumberAnimation、ColorAnimation、RotationAnimation以及State、Transition等,使用這些類型能夠快速實(shí)現(xiàn)界面的動(dòng)畫效果,比如下面展示一個(gè)綠燈閃爍的界面的QML代碼:
import QtQuick 2.0 Rectangle { id: backgroud width: 100 height: 100 color: "grey" Rectangle { id: greenlight width: 60 height: 60 x: 20 y: 20 color: "green" radius: 30 Component.onCompleted: flick.start() SequentialAnimation{ id: flick ColorAnimation { target: greenlight; properties: "color"; to: "black"; duration: 1000 } ColorAnimation { target: greenlight; properties: "color"; to: "green"; duration: 1000 } ColorAnimation { target: greenlight; properties: "color"; to: "black"; duration: 1000 } ColorAnimation { target: greenlight; properties: "color"; to: "green"; duration: 1000 } ColorAnimation { target: greenlight; properties: "color"; to: "black"; duration: 1000 } } } } |
上面的代碼會(huì)使id為greenlight的圖形從綠色變?yōu)楹谏谟珊谏優(yōu)榫G色,重復(fù)三次,模擬綠燈閃爍的效果。由于動(dòng)畫效果不方便以圖片展示,客戶可以自行復(fù)制上面的代碼運(yùn)行查看效果。
從上面的介紹可以看到,QML的語(yǔ)法非常簡(jiǎn)單,整個(gè)文件的結(jié)構(gòu)很清楚,比起使用Qt C++開(kāi)發(fā)界面的更加簡(jiǎn)單快速,不需要管理各種不同的類(class),降低了編程難度,而且整個(gè)界面元素以長(zhǎng)方形為基礎(chǔ)來(lái)搭建,非常適合觸摸屏設(shè)備。另外QML文件不需要編譯,可以直接運(yùn)行,搭建的界面能夠快速的預(yù)覽然后進(jìn)行優(yōu)化,也一定程度上加快了開(kāi)發(fā)速度。當(dāng)然由于QML的設(shè)計(jì)理念,QML只是對(duì)界面顯示進(jìn)行描述,雖然可以內(nèi)嵌JavaScript處理數(shù)據(jù),但是處理數(shù)據(jù)的效率不高,所以顯示所需數(shù)據(jù)的生成、管理還是建議使用Qt C++進(jìn)行處理。這樣底層數(shù)據(jù)能夠高效的進(jìn)行處理,而上層界面又能夠快速搭建,數(shù)據(jù)處理和界面構(gòu)建分離,程序開(kāi)發(fā)分工也更加明確,也更加方便程序的維護(hù)和更新?lián)Q代。
3、使用C++擴(kuò)展QML
Qt提供了C++的函數(shù)接口來(lái)方便的將C++程序中的數(shù)據(jù)提供給QML文件進(jìn)行顯示,這些接口可以分為兩種,一種是直接在C++中注冊(cè)QML類型,然后在C++中執(zhí)行QML文件,這樣QML文件中就可以直接訪問(wèn)注冊(cè)的類型;另一種是創(chuàng)建QML插件,之后可以在QML文件中引入插件,作為獨(dú)立的類型進(jìn)行實(shí)例化。限于篇幅,我們這里只簡(jiǎn)單介紹一下創(chuàng)建QML插件,QML文件代碼基于我們之前一片文章《Linux雙進(jìn)程應(yīng)用示例》中介紹的,插件的功能我們不再具體介紹,只在此使用代碼進(jìn)行展示。
使用qtcreator的指導(dǎo)界面創(chuàng)建QML插件,設(shè)置插件名稱為com.emtronix.qmlcomponents,在QML中通過(guò)語(yǔ)句import com.emtronix.qmlcomponents加載插件,插件編譯過(guò)后以共享庫(kù)的形式存在,需要放到/usr/lib/qt5/qml/com/emtronix/目錄下:
插件使用Qt C++進(jìn)行開(kāi)發(fā),實(shí)現(xiàn)插件的C++類需要繼承QQmlExtensionPlugin類,并且實(shí)現(xiàn)registerTypes()函數(shù),如下:
#include class MsgClientPlugin : public QQmlExtensionPlugin { Q_OBJECT Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: void registerTypes(const char *uri); }; void MsgClientPlugin::registerTypes(const char *uri) { // @uri com.emtronix.qmlcomponents qmlRegisterType } |
上面的代碼qtcreator會(huì)自動(dòng)生成,MsgClient類即為這個(gè)插件注冊(cè)的新的QML類型,之后在QML文件中使用import語(yǔ)句加載插件,就可以在QML文件中實(shí)例化MsgClient類型了。
import com.emtronix.qmlcomponents 1.0 MsgClient{ id: msgclient } |
實(shí)現(xiàn)MsgClient類與Qt中其他的類類似,只要注意需要在QML中能訪問(wèn)的變量需要用Q_PROPERTY宏定義為MsgClient的屬性,而需要在QML文件中訪問(wèn)的函數(shù)需要用Q_INVOKABLE進(jìn)行修飾,如下:
class MsgClient : public QQuickItem { Q_OBJECT Q_DISABLE_COPY(MsgClient) Q_PROPERTY(int m_interface READ interface WRITE setif NOTIFY ifChanged) Q_PROPERTY(QString rmsg READ rmsg WRITE setRmsg NOTIFY rmsgChanged) Q_PROPERTY(QString smsg READ smsg WRITE setSmsg NOTIFY smsgChanged) Q_PROPERTY(int serverConnection READ serverConnection NOTIFY serverConnected()) Q_PROPERTY(DynamicEntryModel* pinstate READ pinstate WRITE setPinState NOTIFY pinStateChanged) Q_PROPERTY(DynamicEntryModel* outSwitch READ outSwitch WRITE setOutSwitch NOTIFY outSwitchChanged) public: MsgClient(QQuickItem *parent = nullptr); ~MsgClient(); Q_INVOKABLE void getAll(); Q_INVOKABLE void getNew(); |
使用slots定義的函數(shù)也可以在QML中直接訪問(wèn),而使用signals定義的消息也可以在QML文件中訪問(wèn):
public slots: void sendMsg(); void setPinState(DynamicEntryModel* obj) { Q_UNUSED(obj) }; void setOutSwitch(DynamicEntryModel* obj) { Q_UNUSED(obj) }; ………. signals: void ifChanged(int id); void newMsgRcved(void); void rmsgChanged(void); void smsgChanged(void); void sendMsgSignal(void); void serverConnected(void); |
這些函數(shù)以及變量都是正常的C++函數(shù)和變量,使用C++來(lái)實(shí)現(xiàn)函數(shù)需要實(shí)現(xiàn)的功能以及操作變量,例如sendMsg實(shí)現(xiàn)如下:
void MsgClient::sendMsg() { struct msg_head buf_h; sprintf((char *)&buf_h.to[0], "S1"); int buf_lenth = m_smsg.size(); buf_h.lenth = buf_lenth; printf("Client sending msg: %d bytes\n", buf_lenth); write(sockedfd, (void *)&buf_h.to[0], 6); write(sockedfd, (void *)m_smsg.data(), buf_lenth); return; } |
signals信號(hào)的訪問(wèn)需要做一定的轉(zhuǎn)換,例如上面的ifChanged消息,在QML中需要使用onIfChanged來(lái)訪問(wèn),即將函數(shù)首字母大寫,然后在前面加上‘on’。
MsgClient類型在QML中的實(shí)際調(diào)用如下:
MsgClient{ id: msgclient m_interface: interfaceId.currentButton onNewMsgRcved:{ getNew() console.log("got new msg" + rmsg) } onIfChanged: { console.log("interface changed to " + msgclient.m_interface) getAll() console.log("all history msg:" + rmsg) } onServerConnected: { notReady.destroy() } } |
可以見(jiàn)到MsgClient類型的使用和QML內(nèi)置的類型使用沒(méi)有什么區(qū)別,而插件中定義的signals消息以及其他可調(diào)用的函數(shù)方法也可以在QML中直接訪問(wèn),MsgClient本身并不會(huì)產(chǎn)生顯示輸出,只是處理數(shù)據(jù)然后提供給QML其他的類型進(jìn)行顯示。我們使用QML搭建了整個(gè)顯示界面,顯示效果如下:
有興趣的客戶可以向我們索要例程的源碼文件。
4、總結(jié)
ESM6802帶有GPU硬件加速模塊,能夠加速Q(mào)ML的渲染,而且QML語(yǔ)法簡(jiǎn)單,使用QML進(jìn)行程序開(kāi)發(fā)能夠快速的構(gòu)建流暢的交互式界面,同時(shí)使用QML開(kāi)發(fā)使得界面開(kāi)發(fā)與程序數(shù)據(jù)處理、硬件管理分開(kāi),明確程序開(kāi)發(fā)的分工,降低程序維護(hù)成本。對(duì)于工業(yè)控制系統(tǒng)來(lái)說(shuō),將界面與底層硬件管理分開(kāi),一定程度上增加了底層硬件管理部分的程序的穩(wěn)定性,而界面又可以實(shí)現(xiàn)快速的迭代,適應(yīng)市場(chǎng)的需求,用戶在使用過(guò)程中可以考慮使用這種方式進(jìn)行程序開(kāi)發(fā)。有興趣的客戶可以參考更多的網(wǎng)上資料以及Qt的官方文檔。在ESM6802的使用過(guò)程中如有問(wèn)題可以和我們聯(lián)系。
-
Linux
+關(guān)注
關(guān)注
87文章
11465瀏覽量
212821 -
嵌入式主板
+關(guān)注
關(guān)注
7文章
6097瀏覽量
36141
發(fā)布評(píng)論請(qǐng)先 登錄
2025第二屆教育信息技術(shù)應(yīng)用創(chuàng)新大賽正式開(kāi)賽
信創(chuàng)浪潮下,國(guó)產(chǎn)主板有什么新的發(fā)展機(jī)遇?

龍芯中科榮獲2024年度信息技術(shù)應(yīng)用創(chuàng)新工作委員會(huì)卓越貢獻(xiàn)成員單位
芯盛智能榮獲2024年信息技術(shù)應(yīng)用創(chuàng)新工作委員會(huì)卓越貢獻(xiàn)成員單位
飛騰助力首屆教育信息技術(shù)應(yīng)用創(chuàng)新大賽圓滿落幕
有方科技參編的信息技術(shù)團(tuán)體標(biāo)準(zhǔn)發(fā)布
龍芯中科助力2024首屆教育信息技術(shù)應(yīng)用創(chuàng)新大賽成功舉辦
拓維信息參與牽頭組建!長(zhǎng)沙新一代信息技術(shù)產(chǎn)教聯(lián)合體正式獲批

中科創(chuàng)達(dá)榮獲2024年軟件和信息技術(shù)服務(wù)優(yōu)秀企業(yè)
引領(lǐng)智能未來(lái):英銳恩科技的國(guó)產(chǎn)低功耗單片機(jī)ENMCU
信創(chuàng)國(guó)產(chǎn)化背景下的工控主板發(fā)展現(xiàn)狀
加速鯤鵬落地!拓維信息信創(chuàng)遷移工具榮獲鯤鵬原生開(kāi)發(fā)技術(shù)認(rèn)證

評(píng)論