QML中使用全局變量

全局變量糊肠,顧名思義就是在程序中到處都能使用的變量皆看。這在一定程度上違背了“模塊化設(shè)計”這個思想龙誊。在筆者剛接觸編程的時候老師就說過全局變量有害,就跟goto一樣春哨;但在實際工程中它其實很有用,使用得當(dāng)?shù)脑挿炊茏屨麄€軟件結(jié)構(gòu)更清晰恩伺、緊湊赴背。本文結(jié)合實際經(jīng)驗向大家介紹在QML程序中如何有效使用全局變量。

全局變量的作用

首先要說明的是晶渠,我們這里說的全局變量不是整數(shù)凰荚、浮點數(shù)這樣的簡單變量,而是復(fù)雜的類對象褒脯。那什么時候會用到全局變量呢便瑟?在筆者的實踐中,一般下面幾種情況會用到全局變量:

  1. 資源共享番川、重用到涂。整個應(yīng)用程序相關(guān)的設(shè)置脊框,比如說程序的版本、風(fēng)格(theme)践啄、字體資源等浇雹,這些數(shù)據(jù)適合放入一個全局變量,從而可以在整個程序的任何地方反復(fù)使用屿讽;
  2. 數(shù)據(jù)傳遞昭灵。全局變量在代碼里都能訪問到,相當(dāng)于一塊共享的內(nèi)存空間伐谈,所以可以在不同的地方傳遞數(shù)據(jù)烂完。但如果是多線程環(huán)境下的話,需要考慮好互斥诵棵;
  3. 事件驅(qū)動窜护。我們可以將該變量申明為QObject子類,然后定義好信號與槽非春,然后在程序需要的地方連接這些信號或者調(diào)用槽函數(shù)柱徙,這樣我們的程序就通過這個全局變量連接起來了。這就相當(dāng)于有了一個核心驅(qū)動奇昙,比如只要一個信號發(fā)出來护侮,程序中所有連接的槽函數(shù)就都會被調(diào)用,而無需關(guān)心是否漏掉了一個储耐。

這幾個特點加起來其實也就是Facebook所推崇的Flux設(shè)計模塊羊初,核心思想簡單講就是把程序的層級關(guān)系變得簡單,單一驅(qū)動什湘。如果你被綜錯復(fù)雜的模塊化設(shè)計弄糊涂了长赞,那可以試試Flux這種清晰明了的設(shè)計思路。

和C++中的使用全局變量相比闽撤,QML中使用起來更加方便得哆,因為QML中有屬性綁定,尤其是上面第三點哟旗,確實可以讓我們的程序“智能化”很多贩据。同時也要說明的是,這里說的“全局”并不是真的全局闸餐,而是指QML執(zhí)行環(huán)境中的全局饱亮;C++中的全局變量不在本文討論范圍之內(nèi)。

QML中定義全局變量

我們知道QML是需要QML引擎(即QQmlEngine)來解釋執(zhí)行的舍沙,所以QML中的全局變量本質(zhì)是QML執(zhí)行上下文(QQmlContext)的屬性近上。定義QML全局變量也就是把我們的對象設(shè)置為QML執(zhí)行上下文的屬性。

有兩種方式:單獨定義拂铡,或者批量定義壹无,其中批量定義又可分為C++形式和QML形式葱绒。我們把這些方法都介紹下。

單獨定義

該方法主要步驟是:

  1. 定義一個QObject的子類格遭,設(shè)計好它的信號哈街、槽還有屬性;

  2. main函數(shù)里構(gòu)建對象拒迅;

  3. QQmlEngine構(gòu)建之后還未加載任何QML文件之前骚秦,將該對象設(shè)置為執(zhí)行上下文的屬性,并取一個合理的名字:

    engine->rootContext()->setContextProperty("$hub", cppBackend);
    

這樣$hub就成為了QML中的全局變量璧微,你可以直接使用它內(nèi)部的各種元數(shù)據(jù)(信號作箍、槽、屬性前硫、枚舉類型等等)胞得。

這里我們約定,用$作為全局變量的開頭字母屹电,這個在JavaScript和QML中是合法的阶剑,便于我們區(qū)分普通局部變量和全局變量。

C++形式批量定義

如果我們的程序比較復(fù)雜危号,把功能都放在一個全局變量里不合適牧愁,我們可以將它們拆開來,用不同的C++類來實現(xiàn)外莲,然后定義一個總的C++類猪半,將這些功能類作為這個總類的屬性,主要步驟是:

  1. 根據(jù)功能定義不同類偷线,例如:
    程序設(shè)置類:

    class Settings : public QObject{
        Q_OBJECT
    public:
        Q_PROPERTY(QString appName MEMBER m_appName)
    private:
        QString m_appName = "MyApp";
    }
    

    和網(wǎng)絡(luò)類:

    class Networks : public QObject{
        Q_OBJECT
    }
    
  2. 定義一個總的類:

    class GlobalObject : public QObject{
        Q_OBJECT
    public:
        Q_PROPERTY(Settings* settings MEMBER m_settings)
        Q_PROPERTY(Networks* networks MEMBER m_networks)
    private:
        Settings* m_settings;
        Networks* m_networks;
    }
    
  3. main函數(shù)中創(chuàng)建總類的對象:

    auto globalObject = new GlobalObject();
    
  4. QQmlEngine構(gòu)建之后還未加載任何QML文件之前磨确,將該對象設(shè)置為執(zhí)行上下文對象:

    engine->rootContext()->setContextObject(globalObject);
    

QML中約定,contextObject的所有屬性都自動變?yōu)?code>contextProperty声邦,就像他們用第一種方法單獨定義一樣乏奥。所以如果需要的功能比較多,建議使用批量定義的方法翔忽,更方便快捷英融。

需要注意,如果一個程序中同時使用了這兩種方法定義全局變量而且有變量重名了歇式,那么以單獨定義的優(yōu)先。

QML形式批量定義

可以用QML文件來代替上面的C++總類胡野。

在定義好SettingsNetworks之后材失,接下去的步驟改為:

  1. 將這些C++類注冊到QML中:

    qmlRegisterType<Settings>("MyCppBackend", 1, 0, "Settings");
    qmlRegisterType<Networks>("MyCppBackend", 1, 0, "Networks");
    
  2. 然后新建一個QML文件:

    //globalobject.qml
    import QtQuick 2.7
    import MyCppBackend 1.0
    
    QtObject {
        id: root
        property var $settings: Settings{}
        property var $networks: Networks{}
    }
    
  3. 將該QML文件作為QML引擎加載的第一個文件:

    engine->load(QUrl("qrc:///globalobject.qml")); 
    

QML引擎約定,加載的第一個QML文件就是contextObject硫豆,所以和C++定義類似龙巨,它的屬性也就成了contextProperty笼呆。

和C++批量定義相比,QML批量定義有如下優(yōu)勢:

  • 變量名前面可以加$旨别,從而方便區(qū)分全局變量和局部變量诗赌,這個在C++定義屬性的時候是不允許的;

  • 如果某個全局變量(一般是QML對象)構(gòu)造很慢秸弛,可以通過QML中的Loader來很方便異步構(gòu)造铭若,從而加速程序啟動:

    property var loader: Loader{
        asynchronous: true
        source: "qrc:/UI/Main.qml"
        onLoaded: {
            // 當(dāng)加載完畢會進(jìn)入這里
        }
    }
    

QML全局變量的中樞作用

最后我們結(jié)合批量定義中的例子來看下QML中全局變量起的數(shù)據(jù)、消息中樞作用递览。這個主要是利用了QML的屬性綁定特性(Property Binding)叼屠。

假如說我們有兩個QML文件:

//View1
import QtQuick 2.7
Item{
    id: root
    Text{
        text: $settings.appName
    }
}

和:

//View2
import QtQuick 2.7
import QtQuick.Controls 2.2
Rectangle{
    id: root
    TextField{
        text: $settings.appName
    }
    Button{
        text: "Click!"
        onClick:{
            $settings.appName = "New Name!";
        }
    }
}

View1View2中的text都和$settings中的appName這個屬性做了綁定。當(dāng)我點擊View2中的按鈕绞铃,$settings.appName被修改镜雨,所有綁定的屬性也就會自動更新,不會遺忘儿捧。由于$settings是全局變量荚坞,這種用法可以深入到任意復(fù)雜、任意層級的界面中菲盾,非常方便颓影。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市亿汞,隨后出現(xiàn)的幾起案子瞭空,更是在濱河造成了極大的恐慌,老刑警劉巖疗我,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咆畏,死亡現(xiàn)場離奇詭異,居然都是意外死亡吴裤,警方通過查閱死者的電腦和手機旧找,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來麦牺,“玉大人钮蛛,你說我怎么就攤上這事∑噬牛” “怎么了魏颓?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吱晒。 經(jīng)常有香客問我甸饱,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任叹话,我火速辦了婚禮偷遗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驼壶。我一直安慰自己氏豌,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布热凹。 她就那樣靜靜地躺著泵喘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪碌嘀。 梳的紋絲不亂的頭發(fā)上涣旨,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音股冗,去河邊找鬼霹陡。 笑死,一個胖子當(dāng)著我的面吹牛止状,可吹牛的內(nèi)容都是我干的烹棉。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼怯疤,長吁一口氣:“原來是場噩夢啊……” “哼浆洗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起集峦,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤伏社,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后塔淤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體摘昌,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年高蜂,在試婚紗的時候發(fā)現(xiàn)自己被綠了聪黎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡备恤,死狀恐怖稿饰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情露泊,我是刑警寧澤喉镰,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站惭笑,受9級特大地震影響梧喷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脖咐,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一铺敌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧屁擅,春花似錦偿凭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至胶果,卻和暖如春匾嘱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背早抠。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工霎烙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蕊连。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓悬垃,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甘苍。 傳聞我的和親對象是個殘疾皇子尝蠕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)载庭,斷路器看彼,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • QML 性能上的注意事項和建議 趙者也[http://www.reibang.com/u/7b2ff27d6fd...
    趙者也閱讀 15,965評論 1 11
  • 1.OC里用到集合類是什么? 基本類型為:NSArray囚聚,NSSet以及NSDictionary 可變類型為:NS...
    輕皺眉頭淺憂思閱讀 1,363評論 0 3
  • 現(xiàn)在是晚上7點18分靖榕。孩子正在寫作業(yè),可是她太累了靡挥。趴在桌子上就睡著了序矩。看見孩子睡得這么香甜跋破,很心疼簸淀,我很...
    91b6f8355762閱讀 217評論 1 1