如何使用QML動態產生Component來完成我們的氣球遊戲 (1)
阿新 • • 發佈:2019-02-09
在這篇文章裡,我們將學習如何使用QML的Qt.createComponent來動態生成我們所需要的Component。這是一個有趣的練習。我希望大家能跟隨我一步一步地完成這個練習。最終使得大家對QML應用有更多的認識。這篇文章中我們也將使用我們的sensor來完成我們其中的一部分功能。在練習之前請大家先去按照安裝Ubuntu SDK來安裝好我們的環境。
1)使用Qt Creator建立一個最基本的應用
我們首先選擇一個“App with Simple UI"的模版來建立我們的最基本的應用。在建立應用的時候,由於應用的package名字中不能出現大寫的字母,所以我們選擇使用小寫的“balloon緊接著,我們填入所需要的資訊來完成我們的應用。
把應用的大小設為如下的值:
width: units.gu(50)
height: units.gu(75)
執行我們的應用:
我們看到,這個應用沒有什麼太多的內容。我們可以嘗試點選按鈕,然後看見方框中的文字發生改變。
2)新增Balloon Component
我們按照如下的圖,用右鍵點選專案"balloon",並選擇“Add New"。我們選擇建立一個叫做“Balloon.qml”的檔案。記住第一個字母為大寫的字母。
至此我們已經建立了一個名字叫做"Balloon.qml"的component,雖然現在它做不了什麼。為了測試我們剛剛已經建立好的Balloon Component,我們把我們的Balloon在main.qml中創建出來。現在我們來修改main.qml檔案:
import QtQuick 2.0 import Ubuntu.Components 1.1 import "components" MainView { // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "com.ubuntu.developer.liu-xiao-guo.balloon" //automaticOrientation: true // Removes the old toolbar and enables new features of the new header. useDeprecatedToolbar: false width: units.gu(50) height: units.gu(75) Page { title: i18n.tr("Balloon") Balloon { width: parent.width/3 height: parent.height/3 x: (parent.width - width) / 2 y: (parent.height - height) /2 } } }
這裡我們把Balloon放到了我們主介面的正中央的位置。重新執行我們的程式,我們可以看到:
顯然,我們可以看到,我們的Balloon component裡沒有任何的東西。只是一個白色方框在那裡。但是,至少,我們可以看到確實Balloon已經能被正確地呼叫。在下面的章節中,我們來一步一步地完成我們的Balloon的功能。
3)完成Balloon模組
請到地址https://github.com/liu-xiao-guo/balloon下載應用,並拷貝應用的"images"目錄到我們已經建立好的專案中(別的檔案不要拷貝)。這樣使得我們的應用有一個叫做"images"的目錄,裡面有我們想要的圖片。開啟我們的Balloon.qml檔案。我們知道Balloon component其實是一個Image的item。我們首先把它設計為如下:
import QtQuick 2.0
Image {
id: balloon
width: 100
height: 250
source: "images/red.svg"
}
我們執行程式,我們發現它的結果如下:
顯然,我們已經看到了我們所需要看到的氣球了。只是它的顏色是固定的紅色。我們想顯示不同的氣球。這時我們需要加入一個顏色的屬性。我們的Balloon.qml的程式碼如下:
Image {
id: balloon
width: 100
height: 250
property string color: "red"
source: "images/" + color + ".svg"
}
預設的顏色我紅色(在沒有定義的情況下)。我們可以嘗試改變我們的main.qml檔案。加入color屬性:
Balloon {
color: "green"
width: parent.width/3
height: parent.height/3
x: (parent.width - width) / 2
y: (parent.height - height) /2
}
再重新執行應用:
我們看見了一個綠色的氣球。顯然它的顏色屬性是起作用的。為了能夠使我們拖動滑鼠移動氣球,我們可以在Balloon.qml的Image中加入如下的程式碼:
MouseArea {
x: 0; y: parent.height/2
width: parent.width
height: parent.height/2
drag.target: parent
drag.axis: "XandYAxis"
}
再重新執行應用。我們嘗試用滑鼠點選氣球的下半部,並移動氣球。我們可以看到氣球隨著滑鼠的移動而移動。下面,我們想在點選氣球的上半部分時,氣球發生爆炸。為了這樣做,我們必須定義另外一個MouseArea來撲捉這個事件。當我們點選氣球的上半部時會發出一個爆破聲。
MouseArea {
x: 0; y: 0
width: parent.width
height: parent.height/2
onClicked: {
balloon.state = "exploded";
player.play();
}
}
為了我們能夠聽到一個聲音,我們也同時定義了一個MediaPlayer。同時記得把剛下載好的程式中的"sounds"目錄考到我們的專案中,並處於和“images”相同的目錄中。
import QtMultimedia 5.0
Image {
...
MediaPlayer {
id: player
source: "sounds/blast.wav"
}
...
}
為了能夠使得我們的應用能夠在手機上播放出聲音,我們必須為它加入我們所需要的security policy。為此,我們必須修改專案的“balloon.apparmor”檔案:
有了“Audio”的policy,我們就可以在我們的手機上聽到一聲“砰”的聲音(在氣球爆炸的時候)。 這裡我們把Image的id定義為"balloon"。當點選氣球的上半部時,我們同時設定balloon的狀態為“exploded”狀態。我們知道,QML設計中可以設定component為不同的狀態。在不同的狀態中,可以定義component中各個item的不同屬性的值。預設的狀態為"",即空串。我們定義的狀態如下:
states: [
State {
name: "exploded"
StateChangeScript {
script: {
// particle.running = true;
}
}
PropertyChanges {
target: balloon
visible: false
source: "images/" + color + "_exploded.png"
}
PropertyChanges {
target: balloon
opacity: 0
}
PropertyChanges {
target: balloon
scale: 0
}
// StateChangeScript { script: balloon.destroy(1000); }
}
]
這時我們重新執行我們的應用,我們會發現我們可以點選球的上半部,並聽到一聲爆破聲。隨後球就消失了。我們的目的達到了,但是,還不是我們最終想要的。這是因為從氣球點選到消失,速度太快了。我們機會沒有看到任何的中間過程。為了我們能夠看到氣球是怎麼爆炸的,我們必須使用一個叫做 transition的。
transitions: [
Transition {
to: "exploded"
SequentialAnimation {
// Disappear
NumberAnimation { target: balloon; property: "opacity"
to: 0; duration: 800 }
NumberAnimation { target: balloon; property: "scale"
to: 0; duration: 800 }
PropertyAction { target: balloon; property: "source"
value: {
if ( !surprise )
"images/" + color + "_exploded.png"
else
"images/flower.png";
}
}
NumberAnimation { target: balloon; property: "opacity"
to: 1; duration: 300 }
NumberAnimation { target: balloon; property: "scale"
to: 1; duration: 300 }
PauseAnimation {
duration: {
if (surprise)
2000
else
800
}
}
PropertyAction { target: balloon; property: "visible"
value: "false"}
}
}
]
有了這個我們可以看到氣球是逐漸消失的。我們在Image中也加入瞭如下的屬性。當這個氣球是一個surprise時,我們會顯示一朵花:
Image {
id: balloon
width: 100
height: 250
property string color: "red"
property bool surprise: true
....
}
為了達到更加逼真的效果,我也為我們的Balloon加入了一個煙花的效果:
import QtQuick.Particles 2.0
...
Image {
...
ParticleSystem {
id: particle
anchors.fill: parent
running: false
Emitter {
group: "stars"
emitRate: 800
lifeSpan: 2400
size: 24
sizeVariation: 8
anchors.fill: parent
}
ImageParticle {
anchors.fill: parent
source: "qrc:///particleresources/star.png"
alpha: 0
alphaVariation: 0.2
colorVariation: 1.0
}
Emitter {
anchors.centerIn: parent
emitRate: 400
lifeSpan: 2400
size: 20 // 48
sizeVariation: 8
velocity: AngleDirection {angleVariation: 180; magnitude: 60}
}
Turbulence {
anchors.fill: parent
strength: 2
}
}
...
}
並在state變化時讓它執行:
StateChangeScript {
script: {
particle.running = true;
}
}
執行應用,效果圖如下:
至此所有的原始碼可以在如下的網址下載: bzr branch lp:~liu-xiao-guo/debiantrial/balloon1
由於篇幅的原因。我們將在下一篇文章中詳細介紹怎麼動態建立很多個Balloon的。大家敬請期待!