註冊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
發表在 Qt、Qt QML |
在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 有兩種方式:
-
使用Qt.createComponent()
-
使用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
發表在 Qt、Qt QML | 標籤有 QML、Qt |
使用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
發表在 Qt、Qt QML | 標籤有 QML、Qt |
發表在 Qt、Qt QML、Qt Quick | 標籤有 QML |
動態建立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
發表在 Qt、Qt QML |
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一個很好的東西,就是signal和slot機制。你能夠很方便的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
發表在 Qt、Qt QML |
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
發表在 Qt、Qt QML |
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賦值
屬性組(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
發表在 Qt、Qt QML | 標籤有 QML、Qt |
一個qml文件的結構
包含模塊
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關鍵字後面的內容能夠有三種:
- 註冊的帶有版本好的模塊
- 指定路徑的qml文件
- 一個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!"
}
}
上面的兩個例子都使用了子對象。這裏引出了一個概念
- QML對象樹中,的父子關係
- 試圖上的父子對象
例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 QML、Qt Quick | 標籤有 QML、Qt |