qt quick中qml編程語言

Qt QML 入門 — 使用C++定義QML類型


註冊C++類

註冊可實例化的類型

若是一個C++類繼承自QObject,若是須要在QML中使用建立對象,則須要註冊爲可實例化的QML類型。html

使用qmlRegisterType()註冊可實例化的QML類型,具體查看qmlRegisterType()的文檔說明。正則表達式

//Message.cpp
class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
    Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
public:
    // ...
};

//main.cpp
#include <QtQml>
...
qmlRegisterType<Message>("com.mycompany.messaging", 1, 0, "Message");
...

//aQmlFile.qml
import com.mycompany.messaging 1.0

Message {
    author: "Amelie"
    creationDate: new Date()
}

註冊不實例化的QML類型

1. qmlRegisterType()不帶參數 這種方式沒法使用引用註冊的類型,因此沒法在QML中建立對象。canvas

2. qmlRegisterInterface() 這種方式用於註冊C++中的虛基類。瀏覽器

3. qmlRegisterUncreatableType()app

4. qmlRegisterSingletonType() 這種方法能夠註冊一個可以在QML中使用的單例類型。dom

附帶屬性

在QML語法中有一個附帶屬性的概念。函數

這裏使用C++自定義QML類型的時候,也能夠定義附帶屬性。工具

核心的亮點就是佈局

static <AttachedPropertiesType> *qmlAttachedProperties(QObject *object);post

QML_DECLARE_TYPEINFO() 中聲明 QML_HAS_ATTACHED_PROPERTIES標誌

例如:

//Message.cpp
class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged)
    Q_PROPERTY(QDateTime creationDate READ creationDate WRITE setCreationDate NOTIFY creationDateChanged)
public:
    // ...
};


//MessageBoardAttachedType.cpp
class MessageBoardAttachedType : public QObject
{
    Q_OBJECT
    Q_PROPERTY(bool expired READ expired WRITE expired NOTIFY expiredChanged)
public:
    MessageBoardAttachedType(QObject *parent);
    bool expired() const;
    void setExpired(bool expired);
signals:
    void published();
    void expiredChanged();
};

//MessageBoard.cpp
class MessageBoard : public QObject
{
    Q_OBJECT
public:
    static MessageBoard *qmlAttachedProperties(QObject *object)
    {
        return new MessageBoardAttachedType(object);
    }
};
QML_DECLARE_TYPEINFO(MessageBoard, QML_HAS_ATTACHED_PROPERTIES)

//在QML中的使用
Message {
    author: "Amelie"
    creationDate: new Date()

    MessageBoard.expired: creationDate < new Date("January 01, 2015 10:45:00")
    MessageBoard.onPublished: console.log("Message by", author, "has been
published!")
}

//main.cpp
...
Message *msg = someMessageInstance();
MessageBoardAttachedType *attached =
        qobject_cast<MessageBoardAttachedType*>(qmlAttachedPropertiesObject<MessageBoard>(msg));
qDebug() << "Value of MessageBoard.expired:" << attached->expired();
...

MessageBoard這個類中首先實現了static *qmlAttachedProperties(QObject *object),而後又用QML_DECLARE_TYPEINFO(MessageBoard, QML_HAS_ATTACHED_PROPERTIES)聲明MessageBoard爲附帶屬性。


水平有限,還請不吝指正!

文章屬原創,轉載請註明轉自>>[Thuai’s blog][http://www.thuai.com]

文章連接>>http://www.thuai.com/archives/154

發表在 QtQt QML 發表回覆

Qt QML — QML 和 JavaScript 整合


在QML中使用JavaScript

PRAGAM LIBRARY

C/C++中關鍵字#pragam,就是指定編譯器執行一些特定動做的指令。這裏也能夠在JavaScript中使用這個關鍵字,告訴編譯器生成一個shared library。

由於在QML component 中若是使用了JavaScript文件,則會每一個component都會有 獨立的 JavaScript實例 的 copy,可是若是咱們不想每一個Component都有獨立的JavaScript實例呢?這怎麼辦呢?

這時候就須要在JavaScript文件中使用.pragam library告訴編譯器,這個JavaScript文件是能夠共享的。

導入JAVASCRIPT

一樣也是使用import來導入JavaScript文件到QML文件中使用。

例如:

import "./myJs" as MyJs

這裏我使用相對路徑來指定js文件,也可使用絕對路徑來指定js文件。爲何這樣寫呢?其實這就是告訴編譯器,須要使用到的qml文件和js文件的目錄位置方便引用解析。如此,你能夠將QML文件和js文件按照層級關係和不一樣的做用,分類放置不用放在和main.qml文件同級目錄,從而有個清晰的項目文件結構。

在JAVASCRIPT文件中引用其餘JAVASCRIPT文件

QtQuick1.x中是不支持,在js文件中引用另外的非無狀態js文件的。

QtQuick2.0版本則支持在一個非無狀態的js文件中引用另一個無狀態的js文件或者QML模塊。

使用.pragam library定義無狀態的JavaScript。

使用.imports則能夠導入其餘js文件和QML模塊。

.import TypeNamespace MajorVersion.MinorVersion as Qualifier

使用Qt.include包含其餘非無狀態的js文件。文檔中有這樣一個例子,能夠很明瞭的看出如何使用Qt.include

//main.qml
import QtQuick 2.0
import "script.js" as MyScript

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            MyScript.showCalculations(10)
            console.log("Call factorial() from QML:",
                MyScript.factorial(10))
        }
    }
}

// script.js
Qt.include("factorial.js")

function showCalculations(value) {
    console.log("Call factorial() from script.js:",
        factorial(value));
}

// factorial.js
function factorial(a) {
    a = parseInt(a);
    if (a <= 0)
        return 1;
    else
        return a * factorial(a - 1);
}

script.js中使用Qt.include來包含factorial.js,而在main.qml文件中只是使用了一個qualifier MyScript就訪問了兩個js文中定義的function。

使用JavaScript動態建立QML object

動態建立QML object 有兩種方式:

  1. 使用Qt.createComponent()

  2. 使用Qt.createQmlObject()

若是你自定義了一個QML組件,則使用Qt.createComponent()動態建立對象會方便一些。方便重用自定義component。

能夠參看個人這篇Qt QML– 動態建立QML objects和銷燬

JavaScript的運行環境

QML引擎提供的JavaScript運行環境和瀏覽器提供的JavaScript運行環境是不同的。QML的運行環境實現了」ECMAScript Language Specification」的標準,支持ECMAScript標準的內建類型和函數,如Object,Array,Math等。關於詳細的ECMAScript標準有哪些內建類型,能夠參看ECMA-262 第5版的文檔。


水平有限,還請不吝指正,謝謝!

文章屬原創,轉載請註明轉自>>Thuai’s blog

文章連接>>http://www.thuai.com/archives/118

發表在 QtQt QML 標籤有 QMLQt 發表回覆

Qt QML — 調試QML程序


使用Console調試

Log

console.log 打印日誌信息

console.debug 打印調試信息

console.info 打印普通訊息

console.warn 打印警告信息

console.error 打印錯誤信息

Assert

就像C++就的assert,判斷表達式是否成立。QML中的console.assert在表達式不成立時並不會終止程序,而是會打印出錯誤的代碼位置。

console.assert 斷言

Timer

console.time 和 console.timeEnd 用來查看代碼運行所花費的時間。

Trace

在JavaScript的函數中加入console.trace()就能夠跟蹤代碼的調用過程,可是隻可以跟蹤最後的10次調用。

Count

console.count 會打印出代碼調用的次數

Profile

JavaScript 函數的性能分析, console.profile 開始,console.profileEnd 結束。

Exception

console.exception 打印出錯誤信息和堆棧調用信息。


包含模塊的調試 (Debugging module imports)

添加環境變量QML_IMPORT_TRACE=1,能夠查看import的module是否正確。而後在終端中使用qmlscene命令運行指定的qml文件,終端就會輸出import信息。


水平有限,還請不吝指正,謝謝!

原創文章,轉載請註明轉自>>Thuai’s blog

文章連接>>http://www.thuai.com/archives/123

發表在 QtQt QML 標籤有 QMLQt 發表回覆

Qt Quick 2 — QML類型(QML Types)


注意: 末尾寫了一個2的,表示QtQuick2中才出現的。對於部分新出現的一些類型,我本身也不怎麼熟悉,因此暫時不寫中文,省得誤人子弟就很差了。之後我會再次更新這篇文章。

可視類型 (visual types)

  • Item — QML 基本的試圖類型,其餘可視類型都是從Item繼承來的
  • Rectangle — 矩形區域
  • Image — 圖片
  • BorderImage — 邊框背景
  • AnimatedImage — 播放一張GIF圖片
  • AnimatedSprite — 播放一系列幀動畫 2
  • SpriteSequence — 播放一系列幀動畫中的部分幀 2
  • Text — 顯示文本
  • Window — 顯示一個頂層窗口 2

可視的實用功能項 (Visual Item Utility)

  • Accessible — 提供Component的獲取性 2
  • Gradient — 漸變
  • GradientStop — 漸變閾值
  • SystemPalette — 系統調色板
  • Screen — 獲取設備的屏幕寬高橫向參數 2
  • Sprite — 顯示特定的Sprite動畫 2
  • FontLoader — 字體加載器

可視項的生成器 (Visual Item Generation)

  • Repeater — 可以根據model生成多個可視化的項
  • Loader — QML component動態加載器

可視項的變換 (Visual Item Transformations)

  • Transform — 變形 2
  • Scale — 縮放
  • Rotation — 旋轉
  • Translate — 平移

獲取用戶輸入 (User Input)

  • MouseArea — 鼠標區域
  • Keys — 按鍵
  • KeyNavigation — 導航鍵 2
  • FocusScope — 焦點區域
  • Flickable — 橡皮筋區域
  • PinchArea — 捏拽區域
  • MultiPointTouchArea — 多點觸控區域 2
  • Drag –拖動區域 2
  • DropArea — 掉落區域 2
  • TextInput — 文本輸入區域
  • TextEdit — 文本編輯區域

文本輸入的實用工具項 (Text Input Utility)

  • IntValidator — 整數校驗器
  • DoubleValidator — 雙精度浮點校驗器
  • RegExpValidator — 正則表達式校驗器

用戶輸入事件 (User input events)

  • TouchPoint — 觸摸點擊事件 2
  • PinchEvent — 捏拽事件
  • WheelEvent — 鼠標滾輪事件 2
  • MouseEvent — 鼠標點擊事件
  • KeyEvent — 按鍵事件
  • DragEvent — 拖動事件 2

位置 (Positioning)

  • Positioner — Item在scene中的位置信息(附帶屬性) 2
  • Column — 子對象豎直方向排列
  • Row — 子對象水平方向排列
  • Grid — 子對象按照網格形式排列
  • Flow — 流動
  • LayoutMirroring — 佈局鏡像(附帶屬性) 2

狀態 (States)

  • State — 狀態
  • PropertyChanges — 屬性變動
  • StateGroup — 狀態組
  • StateChangeScript — 狀態變動腳本
  • ParentChange — 父對象變動
  • AnchorChanges — 錨點變動

轉變和動畫 (Transitions and Animations)

  • Transition — 轉變更畫
  • ViewTransition — 視圖轉變 2
  • SequentialAnimation — 串行動畫序列
  • ParallelAnimation — 並行動畫序列
  • Behavior — 特定屬性變化時的行爲
  • PropertyAction — 在動畫序列中執行屬性變動動做
  • SmoothedAnimation — 屬性值平滑變化動畫
  • SpringAnimation — 彈力動畫
  • ScriptAction — 在動畫序列中執行腳本(主要用於動畫中執行腳本)

與類型相關的動畫 (Type-specific Animations)

  • PropertyAnimation — 屬性動畫
  • NumberAniamtion — 數值動畫
  • Vector3dAnimation — Vector3d屬性的動畫
  • ColorAnimation — color屬性的動畫
  • RotationAnimation — rotation屬性的動畫
  • ParentAnimation — parent屬性動畫
  • AnchorAnimation — anchor屬性動畫
  • PathAnimation — path動畫 2

底層動畫 (Lower-level Animation Types)

  • PathInterpolator — path修改器 2
  • AnimationController — 動畫控制器 2

路徑動畫 (Animation paths)

  • Path — 路徑
  • PathLine — 路徑爲直線
  • PathQuad — 路徑爲二次方程式貝爾曲線
  • PathCubic — 路徑爲三次方程式貝爾曲線
  • PathArc — 路徑爲弧線 2
  • PathCurve — 路徑爲曲線 2
  • PathSvg — SVG 路徑 2
  • PathAttribute — 在path中設置屬性
  • PathPercent — 修改path中item的間距

數據模型 (Model and Model Data)

  • ListModel
  • ListElement
  • VisualItemModel
  • VisualDataModel
  • VisualDataGroup
  • XmlListModel
  • XmlRole

視圖 (Views)

  • ListView
  • GridView
  • PathView
  • Pack age

數據存儲 (Data Storage)

  • QtQuick.LocalStorage 2 — 本地存儲模塊 2

圖形效果 (Graphical Effects)

  • Flipable
  • ShaderEffect 2
  • ShaderEffectSource
  • GridMesh 2
  • QtQuick.Particles 2 2

實用方便的類型 (Convenience Types)

  • Connections
  • Binding — 綁定器
  • Timer — 定時器
  • WorkScript

畫布 (Canvas)

  • Canvas 2
  • Context2D 2
  • CanvasGradient 2
  • CanvasPixelArray 2
  • CanvasImageData 2
  • TextMetrics 2

水平有限,還請不吝指正,謝謝!


原創文章,轉載請註明 >> Thuai’s blog

文章連接 >>http://www.thuai.com/archives/122

發表在 QtQt QMLQt Quick 標籤有 QML 發表回覆

Qt QML– 動態建立QML objects和銷燬


動態建立Qml對象

使用JavaScript動態建立Qml對象有兩種方式,一是使用Qt.createComponent,二是使用Qt.createQmlObject

若是你已經有一個qml文件定義了一個component,則使用Qt.createComponent()這種方式會比較好。若是自己對象就是在Qml運行期生成的對象且簡單,則使用Qt.createQmlObject(),你確定不想在一條語句中寫上百來行代碼定義一個component對吧!

QT.CREATECOMPONENT

先看代碼

//Sprite.qml
import QtQuick 2.0

Rectangle { width: 80; height: 50; color: "red" }

//main.qml
import QtQuick 2.0
import "componentCreation.js" as MyScript

Rectangle {
    id: appWindow
    width: 300; height: 300

    Component.onCompleted: MyScript.createSpriteObjects();
}

//componentCreation.js
var component;
var sprite;

function createSpriteObjects() {
    component = Qt.createComponent("Sprite.qml");
    if (component.status == Component.Ready)
        finishCreation();
    else
        component.statusChanged.connect(finishCreation);
}

function finishCreation() {
    if (component.status == Component.Ready) {
        sprite = component.createObject(appWindow, {"x": 100, "y": 100});
        if (sprite == null) {
            // Error Handling
            console.log("Error creating object");
        }
    } else if (component.status == Component.Error) {
        // Error Handling
        console.log("Error loading component:", component.errorString());
    }
}

從上面的代碼看出,先自定義了一個qml文件Sprite.qml,這個qml文件中有個寬80、高50、顏色爲紅色的Rectangle組件。在main.qml首先是導入了componentCreation.js這個JavaScript腳本,並去了別名MyScript。rootObject則是一個寬300、高300、id爲appWindow的Rectangle組件。當這個Rectanle類型的組件加載完成的時候就會調用componentCreation.js中的createSpriteObjects()方法動態建立對象。

核心就是createSpriteObjects()這個方法了。

能夠看出使用Qt.createComponet()這種方法動態建立qml對象,須要兩個步驟:1.使用Qt.createComponent(url,parent, mode). url即爲自定義好的須要建立qml對象的qml文件。parent和mode一般能夠不寫。具體能夠查看文檔中Qt.createComponent()的詳細說明。由於Qt.createCompoent()成功則會返回一個Component類型的對象,因此須要第二步。2.使用createObject()建立實例,createObject()方法是Component類型的一個方法。createObject()返回的纔是Script.qml的實例。

在上面的這段代碼中,還能夠看到,component.statusChanged這個signal鏈接了一個createScriptObjects.js中的另一個方法,經過component.status和Component組件中的不一樣枚舉值對比,進行錯誤的判斷和處理。

總結: Qt.createComponent()這個function是 Qt 這個Qml全局類型中的一個方法,這個方法返回一個Component類型的對象。須要獲得自定義qml組件的實例,還須要使用Component.createObject()方法。若是須要使用非阻塞方式建立qml object則可使用incubateObject()方法。

QT.CREATEQMLOBJECT()

若是須要在qml運行期建立一個qml對象且這個對象定義並不複雜時,則使用Qt.createQmlObject()這種方法比較好。

import QtQuick 2.0

Rectangle {
    id: rect
    width: 360
    height: 360
    Text {
        anchors.centerIn: parent
        text: "Hello World"
    }
    MouseArea {
        anchors.fill: parent
        onClicked: {
            createObject();
        }
    }

    function createObject()
    {
        //第一種寫法
        /*
        var object = Qt.createQmlObject('import QtQuick 2.0;' +
                                        'Rectangle {' +
                                        'width:30; ' +
                                        'height:30;' +
                                        'colo: "red"}', rect, "error");
        */

        //第二種寫法
        //var newObject = Qt.createQmlObject('import QtQuick 2.0; ' + 'Rectangle { width: 20; height: 20; colo: "red"}', rect, "dynamicSnippet1");

        //第三種寫法
        var newObject = Qt.createQmlObject('import QtQuick 2.0; \n Rectangle {width: 20; height: 20; colo: "red"}', rect, "error3");
   }
}

從上面的代碼能夠看出Qt.createQmlObject()有三個參數,第一個爲定義qml對象的字符串。第二個爲建立的qml對象的父對象。第三個則爲出錯時候的文件路徑提示。而且提示會出現行數和列數,能夠分別試驗三種寫法看錯誤提示有何不一樣。

維護動態建立的Qml對象

動態建立Qml對象,你必須知道它所存在的context的生命週期,必須保證context的生命週期比動態建立的Qml對象生命週期要長,由於context銷燬了,其中綁定的動態建立的Qml對象也會失效。動態建立的Qml對象的context取決於它建立的方式。

  • Qt.createComponet(),使用這種方法,則context就是調用這個Qt.createComponent方法的QQmlContext。QQmlContext跟Qt4.8.x中的QDecalartiveContext()其實差很少。

  • Qt.createQmlObject(),使用這種方法,則context就是這個方法的的parent參數。

  • 若是使用Component{}定義一個對象,而後在這個Component對象中調用createObject()或者incubateObject()方法,這時動態建立出的對象的context就是這個Component的context。

動態銷燬對象

使用Object.destroy()方法刪除對象。

在多數狀況下,你可使用改變可視對象的opacity值爲0或者將它移出屏幕就能夠了,而不是delete它。若是你有不少動態建立的對象,delete那些不用的對象,則是值得作的事情。

記住,不要去刪除不是你手動建立的對象,例如Repeater和Loader建立的對象。

例以下面這段代碼中SelfDestroyingRect就不能使用destroy來銷燬它。

Item {
    SelfDestroyingRect {
        // ...
    }
}

水平有限,還請不吝指正,謝謝!

文章屬原創,轉載請註明轉自>>Thuai’s blog

文章連接>>http://www.thuai.com/archives/119

發表在 QtQt QML 發表回覆

Qt QML—QML signal與signal handler系統

QML 的signal 和 signal handler機制的存在,是爲了應用可以和UI組件之間相互交互。signal就是button clicked、mouse area pressed這些event,signal handler則就是這些事件的響應。

當一個signal emitted,相應的signal handler就會被調用,在signal handler中執行一些scripts或是其餘操做,已完成event的響應。

signal和signal handler的定義

signal

signal <signalName>[([<type> <parameter name>[, ...]])]

signal handler

on<SignaleName>

能夠參考另外一篇文章 Qt QML入門– QML 語法 (2)

Property Change Signal Handler

當Property的值改變了,就會自動emitted一個signal,這種property changed signal,有property Signal handler與之對應。你只須要實現signal handler便可。

on<PropertyName>Changed

使用Connections Type

不少人都知道Qt一個很好的東西,就是signalslot機制。你能夠很方便的connect的signal和slot。QML中的Connections,它可以讓你接收指定object的任意signal,從而可以在signal聲明的那個Object以外接收到聲明的signal,從而實現本身想要logic。

import QtQuick 2.0

Rectangle {
    id: rect
    width: 100; height: 100

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    Connections {
        target: mouseArea
        onClicked: {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

上面的代碼中,Connections中的target綁定的是ouseArea,從而在rect中可以接收到mouseArea的signal,如clicked、pressed、released等等signal。

附帶的signal handler

附帶的signal handler是附帶組件的signal與之對應的signal handler,並非使用附帶組件自己Object的signal的signal handler。

能夠參看另外一篇文章 Qt QML入門– QML 語法 (2)

signal與signal的鏈接,signal與method的鏈接

signal 都有一個connect()方法,能夠鏈接method或者signal。

能夠看下面兩段代碼

signal connect signal

Rectangle {
    id: forwarder
    width: 100; height: 100

    signal send()
    onSend: console.log("Send clicked")

    MouseArea {
        id: mousearea
        anchors.fill: parent
        onClicked: console.log("MouseArea clicked")
    }

    Component.onCompleted: {
        mousearea.clicked.connect(send)
    }
}

注意:mousearea.clicked.connect(send),這裏send是signal可是卻沒有加或括號。emitted signal的時候則不管是否signal聲明的時候有無括號,都需要加上括號。

signal connect method

Rectangle {
    id: relay

    signal messageReceived(string person, string notice)

    Component.onCompleted: {
        relay.messageReceived.connect(sendToPost)
        relay.messageReceived.connect(sendToTelegraph)
        relay.messageReceived.connect(sendToEmail)
    }

    function sendToPost(person, notice) {
        console.log("Sending to post: " + person + ", " + notice)
    }
    function sendToTelegraph(person, notice) {
        console.log("Sending to telegraph: " + person + ", " + notice)
    }
    function sendToEmail(person, notice) {
        console.log("Sending to email: " + person + ", " + notice)
    }
}

注意:這裏使用connect鏈接是的method,一樣沒有加上括號。

既然可以connect,那有沒有disconnect呢?固然有。

有時候,你不使用disconnect,你某些動態create的對象都沒法distroy。

Rectangle {
    id: relay
    //...

    function removeTelegraphSignal() {
        relay.messageReceived.disconnect(sendToTelegraph)
    }
}

disconnect跟connect就只是一個單詞差異而已,沒有其餘特別不一樣的地方。


水平有限,還請不吝指正,謝謝!


原創文章,轉載請註明 >> Thuai’s blog

文章連接 >>http://www.thuai.com/archives/116

發表在 QtQt QML 發表回覆

Qt QML—QML 屬性的綁定(Property Binding)

QML 屬性綁定 (Property Binding)

屬性的綁定可以更好的使用QML的特性-QML object動態行爲變化的自動響應。這是QML一個很重要的特性。

注意:綁定的一個很重要的標誌就是「:」–冒號

當QML object 的屬性既能夠分配一個static value,也能夠綁定一個JavaScript表達式,也可使用JavaScript的自帶的Date Math這些對象。由於QML uses a standards compliant JavaScript engine。

Rectangle {
    id: parentRect
    width: 200; height: 200

    Rectangle {
        id: childRect
        width: 100; height: parent.height
        color: "blue"
    }
}

上面的代碼中,childRect的height綁定到了parent的height,當parentRect的height改變的時候,QML engine會從新計算childRect.height

import QtQuick 2.0

Rectangle {
    width: 100
    height: width * 2
    focus: true
    Keys.onSpacePressed: {
        height = width * 3
    }
}

在看上面的這段代碼,Rectangle的height首先綁定了width2,而後在Key.onSpacePressed這個附帶的signal handler中,height 被賦值width3,注意是賦值,不是綁定。

因此以前的bind被這個賦值語句移除了,也就是說之後Rectangle的width變化了,height不會自動變成width的2倍。

若是是想要從新binding而不是賦值,則須要使用Qt.binding()。

this的使用

使用JavaScript綁定時,QML容許使用Javascript中this關鍵字。

例以下面的代碼:

Item {
    width: 500
    height: 500

    Rectangle {
        id: rect
        width: 100
        color: "yellow"
    }

    Component.onCompleted: {
        rect.height = Qt.binding(function() { return this.width * 2 })
        console.log("rect.height = " + rect.height) // prints 200, not 1000
    }
}

rect.heigth屬性的綁定使用了JavaScript的語句,因此可使用this,這裏的this表示的是Item而不是rect


水平有限,還請不吝指正,謝謝!


原創文章,轉載請註明 >> Thuai’s blog

文章連接 >>http://www.thuai.com/archives/115

發表在 QtQt QML 發表回覆

Qt QML入門– QML 語法 (2)


QML 對象的屬性

一個QML對象所具備的屬性有如下幾種:

  • id -id 標識
  • property attributes –屬性(其中包括繼承自Item的attributes,自定義的attributes)
  • signal attributes –信號
  • signal handler attributes –信號處理
  • method attributes –函數
  • attached propeties and attached signal handler attributes –附帶的屬性 和 附帶的signal handler

id

id 用來標識QML對象,id不可以以大寫字母開頭,一樣method也不可以以大寫字母開頭。請記住這點,否則就會有「xxx cannot begin with an upper case letter」這樣的error。 有了id你就可以經過id引用id爲xxx的對象了。因此儘可能的給你的每一個QML object都寫上id吧! QML object 一旦實例化,id值就沒法改變。


Property Attributes

自定義屬性的語法格式:

[default] property <propertyType> <propertyName>

例如:

property int myAge 25;
default property string myName thuai

//MyCustomRectangle.qml
property MyCustomRectangle myCusRect
property color myFavoriteColor: "blue"

default關鍵字表示,該QML object有個默認屬性,你使用這個屬性的時候不須要顯式的聲明。

例如:

// MyLabel.qml
import QtQuick 2.0

Text {
    default property var someText

    text: "Hello, " + someText.text
}

上面的MyLabel類型中中有個default屬性someText,因此在MyLable使用的時候,

MyLabel {
    Text { text: "world!" }
}

//和這段代碼是等效的
MyLable {
    someText: Text { text: "world!" }
}

這就是default property

單行語句的分號是可寫不用寫的。可是一行寫多條語句,語句則必需要用分號分隔!

propertyType 能夠是QML的基本類型,一種QML對象類型,也能夠是QML能夠是C++經過Q_PROPERTY宏註冊的類,還能夠是JavaScript中的var,var它能夠表示任何類型的數據,還能夠是自定義的QML類型,如MyCustomRectangle

爲PROPERTY ATTRIBUTES賦值

  • 一是初始化的時候賦值

    import QtQuick 2.0 Item{ x: 10 y: 10 width: 100 height: 100 }

  • 一是使用的時候賦值。

    import QtQuick 2.0 Rectangle { id: rect Component.OnCompleted: { rect.color = 「blue」 } }

屬性組(GROUPED PROPERTIES)

將相同的屬性寫成一句代碼 例如:

Text {
    //dot notation
    font.pixelSize: 12
    font.b: true
}

Text {
    //group notation
    font { pixelSize: 12; b: true }
}

font.pixelSize 和 font.blod用括號括起來寫成了一句,注意 pixelSize和 b之間有個;

屬性別名(PROPERTY ALIASES)

格式: [default] property alias <name>: <alias reference>

// Button.qml
import QtQuick 2.0

Rectangle {
    property alias buttonText: textItem.text

    width: 100; height: 30; color: "yellow"

    Text { id: textItem }
}

Button中的屬性buttonText是textItem.text屬性的別名

Button { buttonText: "Click Me" }

因此對Button的buttonText屬性賦值就至關於給Text的text屬性賦值

注意: Property Aliases 必須在組件全部初始化工做都完成以後,纔可以使用,不然會出錯。

import QtQuick 2.0

Rectangle {
    width: 360
    height: 360

    property alias aText: te

    //error before Rectangle initialized completed
    //aText: "init text"

    Component.onCompleted: {
        aText.text = "init text onCompleted"
    }

    Text {
        id: te
        anchors.centerIn: parent
    }
}

若是你在component初始化完成,對alias properties賦初始值,QtCreator會報「Cannot assign to non-existent property 「aText」錯誤!

這裏又看到了一個有意思的東西。Component.onCompleted,這是一個QtQuick全部的Object都有的一個附帶信號處理函數。組件初始化建立完成就會觸發這個處理函數。後面在關於signal的文章中有更詳細的講解。

PROPERTY MODIFIER OBJECTS

<PropertyModifierTypeName> on <propertyName> {
    // attributes of the object instance
}

這裏Property Modifier Objects我沒有用中文,由於我也不知道該譯成什麼。具體後面的例子中你們能夠看到Property Modifier Objects的應用。以下面代碼中的NumberAnimation

import QtQuick 2.0

Rectangle {
    width: 360
    height: 360

    Rectangle {
        id: moveRect
        width: 50
        height: 50
        radius: 5
        color: "red"

        NumberAnimation on x {
            from: 0
            to: 100
            duration: 200
        }
    }
}

信號(Signal Attributes)

信號屬性定義語法:

signal <signalName>[([<type> <parameter name>[, ...]])]

[]表示可選

例如:

//不帶參數和括號
signal mySignal

//帶空括號
signal mySignal2()

//signal 信號名(參數類型 參數名, 參數a類型 參數a)
signal mySignal3(string name, var any)

對應的signal handler的語法格式則是:

on<SignalName>

如上例中的mySignal,對應的signal handler 就寫成 onMySignal

注意: mySignal的第一個字母S成了大寫的了。由於這裏onMySignal,on做爲開頭了。因此按照QML的語法,mySignal中的m就要寫成M, signal 還能夠如下劃線_開頭, 好比_mySignal4,對應的signal handler則寫成on_MySignal4,下劃線的數目也能夠不一樣。再好比__mySignal4和_mySignal4**就是兩個不一樣的signal(前者一個下劃線,後者兩個下劃線)

signal mySignal3的 signal handler:

onMySignal3: {
     console.debug("i'm a signal handler")
     console.debug("name"en);
}

QML有內建的屬性signal,當屬性的value變化的時候,就會emitted signal. 這個就是文檔中所說的Property Changed Signal

import QtQuick 2.0

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Click!")
        }
    }
}

MouseArea有clicked signal, 當鼠標點擊MouseArea 的時候,就會emit clicked signal。 signal handler onClicked 就會觸發,console 就會打印出「Click!「

Signal Handler是一種特殊的method屬性。當你在QML中文件中聲明一個singal的時候,QML會自動幫你關聯一個signal handler,這個signal handler默認是沒有實現的。因此你只須要實現這個signal handler就能夠了,而後在emitted一個signal的時候,與之關聯的signal handler就會自動的被QML引擎調用。

例如文檔中的一個例子:

// SquareButton.qml
Rectangle {
    id: root

    signal activated(real xPosition, real yPosition)
    signal deactivated //注意我沒有括號哦!

    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onPressed: root.activated(mouse.x, mouse.y) //emit activated signal and parameter
        onRelased: root.deactivated() //emit deactivated signal 注意我有括號哦!
    }
}

// myapplication.qml
SquareButton {
    //implement onActivated signal
    onActivated: console.log("Activated at " + xPosition + "," + yPosition) 
    //implement onDeactivated signal
    onDeactivated: console.log("Deactivated!")
}

在SquareButton.qml中的MouseArea,pressed、released都emitted了一個signal。 由此能夠看出QML中emitted一個signal,你只須要調用它就好了。

注意:在QML中聲明無參signal你能夠不帶括號,可是emitted它的時候,就必需要帶括號了。不然,它不會報錯,可是它也不會emitted signal

而在Qt C++代碼中你要想emittd一個signal,你就必須使用emit <定義的信號>,纔可以emit一個signal。

在myapplication.qml中你使用SquareButton這個自定義的Component時,只需實現下onActivated、onDeactivated這兩個signal handler就行,由於QML已經幫你declare並connected了。

signal不只有signal handler,它還能夠與後面講到的method鏈接(connect),Qt 一個很重要的機制就是信號和槽機制,其實在QML中也有這個,只是叫法不同而已。QML中全部的method都是slot。

PROPERTY CHANGE SIGNAL HANDLERS

語法格式:

on<Property>Changed

signal 有signal handler,property呢? property有property changed signal handler(屬性變化信號處理方法,呵呵有點拗口,翻譯水平不行,不糾結在這種意會的層次,可以理解就行),既然也是signal hanlder那就不須要你去declare它並關聯到信號了。你也只須要使用它就好了。

例文檔中的:

import QtQuick 2.0

TextInput {
    text: "Change this!"
    onTextChanged: console.log("Text has changed to:", text)
}

方法(Method Attributes)

QML定義一個method:

function <functionName>([<parameterName>[, ...]]){ <body> }

QML中的method定義不像signal的定義,須要聲明參數(parameter)的類型(type),QML中method的參數類型是var,也只能是var,不論它是在QML中定義的method仍是C++中定義的指定參數的method而後註冊到QML system中使用的。

對JavaScript熟悉的朋友,應該知道var這個關鍵字。(此處能夠問歌哥或者度娘,建議歌哥,由於度娘都是copy的類似答案)

這是QML定義method的語法格式,C++中的method,能夠用Q_INVOKABLE和 slots註冊到QML系統中,這樣QML中就能夠訪問你C++中寫的method方法了。具體我會在後面關於C++與QML交互的文章中詳細表述。

這裏先暫不寫JavaScript中的method如何在QML object中訪問。先理解QML object定義的method如何正確使用,再拓展其餘方法定義的method如何使用。

import QtQuick 2.0

Item {
    width: 200; height: 200

    MouseArea {
        id: msArea
        anchors.fill: parent
        onClicked: label.moveTo(mouse.x, mouse.y)
    }

    Text {
        id: label
        function moveTo(newX, newY) {
            label.x = newX;
            label.y = newY;
        }
        text: "Move me!"
    }
}

上面的代碼中,id爲label的Text中有個method moveTo(newX, newY) 更改label的x、y值,從而移動label,當點擊Item中的任意一點,Item中MouseArea msArea自動emitted clicked signal, signal handler onClicked 自動調用label.moveTo()。

從這個例子,你應該可以理解了如何定義一個QML method以及如何調用一個QML method。因此我建議我同事都最好每一個component都加上id,不要圖少敲幾個鍵,而讓代碼的可讀性下降。

附帶的屬性和附帶的信號處理函數 (Attached Properties and Attached Signal Handlers)

定義的語法格式:

<AttachingType>.<propertyName>

<AttachingType>.on<SignalName>

import QtQuick 2.0

ListView {
    width: 240; height: 320
    model: 3
    delegate: Rectangle {
        width: 100; height: 30
        color: ListView.isCurrentItem ? "red" : "yellow"
    }
}

在上面的代碼中,isCurrentItem就是ListView的一個附帶屬性。ListView還有不少附帶的屬性,詳見QtCreator中的幫助。

Component.onCompleted則是一個附帶的Signal handler。


水平有限,還請不吝指正!

很是感謝網友lei,爲本文勘正


原創文章,轉載請註明 >> Thuai’s blog

文章連接 >>http://www.thuai.com/archives/100

發表在 QtQt QML 標籤有 QMLQt 發表回覆

Qt QML入門– QML 語法 (1)


一個qml文件的結構

  • 須要包含的模塊
  • 惟一一個root對象

包含模塊

import ModuleIdentifier Version.Number [as <Qualifier>]

例如:

//HelloWorld.qml
import QtQuick 2.0

或者

import QtQuick 2.0 as Quick

詳見文檔–Import Statements

有且僅有一個ROOT對象

import QtQuick 2.0

Rectangle { width: 200; height: 200; color: "red" }
Rectangle { width: 200; height: 200; color: "blue" } // invalid!

這種在一個qml文件中寫兩個root object是錯誤的,只能有一個root object,下面的代碼就是正確的形式。

import QtQuick 2.0

Rectangle { width: 200; height: 200; color: "red" }

qml的基本語法

模塊的包含

QML 模塊的包含,只能使用關鍵字 import 包含qml文件須要用到模塊,import關鍵字後面的內容能夠有三種:

  1. 註冊的帶有版本好的模塊
  2. 指定路徑的qml文件
  3. 一個JavaScript文件

例如:

import QtQuick 2.0
import QtQuick.LocalStorage 2.0 as Database
import "../privateComponents"
import "somefile.js" as Script

其中第一種和第二種都是包含帶有版本號註冊的模塊。

對象的聲明

Rectangle { width: 100 height: 100 color: "red" }

上面的代碼就使用Rectangle元素聲明瞭一個寬100,高100,顏色爲red的對象。

子對象的聲明

例1

import QtQuick 2.0

Rectangle {
      id: rect
      width: 100
      height: 100
      gradient: Gradient {
                id: grad
                GradientStop {id: gStopYellow; position: 0.0; color: "yellow" }
                GradientStop {id: gStopGreen; position: 1.0; color: "green" }
      }
}

例2

import QtQuick 2.0
Rectangle {
    id: rect
    width: 200
    height: 200
    color: "red"

    Text {
        id: text
        anchors.centerIn: parent
        text: "Hello, QML!"
    }
}

上面的兩個例子都使用了子對象。這裏引出了一個概念

  1. QML對象樹中,的父子關係
  2. 試圖上的父子對象

例1中Rectangle對象rect中的gradient屬性中有個子對象grad,grad中又有兩個GradientStop子對象。這些父子對象的上下文環境(context)是QML object tree 中的父子對象關係 ,而不是visual scene 上下文環境的父子對象關係。

例2中的Text與Rectangle的父子關係便是object tree中的父子關係也是visual scene中的父子對象關係。

註釋

和大多數語言同樣,有單行註釋// 和 塊註釋 /* */


水平有限,還請不吝指正,謝謝!

很是感謝網友lei,爲本文堪正!


原創文章,轉載請註明轉自 >> Thuai’s blog

文章連接>> http://www.thuai.com/archives/50

發表在 Qt QMLQt Quick 標籤有 QMLQt 發表回覆

相關文章
相關標籤/搜索