Qt Quick学習ノート(一)QMLインタフェースモデル

7861 ワード

基本文法
QMLはHTMLに似たマーク型言語であり、HTMLと似たツリー型ノード構造があり、JSのような関数文法も含まれている.基本的なQML文書はこのような形です.
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    objectName: "root"
    visible: true
    width: 1280
    height: 720
    maximumHeight: this.height
    minimumHeight: this.height
    maximumWidth: this.width
    minimumWidth: this.width
    title: qsTr("Security Check")
    font.family: "Source Han Sans CN Normal"

    Image{
        x: 0
        y: 0
        property int _test: 8
        property var list: []
    }
}
ApplicationWindowは、インターフェースウィンドウ全体のルートノードであり、C+ファイルで使用することができる.
QObject* rootObject;
rootObject = engine.rootObjects().first();
ルートノードへのポインタが得られ、信号スロットのリンクと関数の呼び出しが容易になる(後述).
元素を宣言する
QMLでは、一つの要素はこのように類似しています.
Image{
    property a: x
    property b: y
}
各要素にはあらかじめ定義された属性があります.具体的に各タイプの元素にはどのような属性がありますか?All QML Typesを参照してください.
動的に要素を追加します.
QMLでは,動的増加要素は一つのテンプレートに基づいており,動的に追加する必要があるすべてのオブジェクトは,まず一つのテンプレート要素の中に存在する必要がある.例えば、Image要素を動的に追加し、このように構築することができる.
    Component{
        id:create
        Image {
            id: tourist
            source: sprites[Math.floor((Math.random()*3))]
            width: 20
            height: 20
            property int x_axid: 1010
            property int y_axid: 120
            x:x_axid
            y:y_axid
            Behavior on x{
                SmoothedAnimation{ duration: 500 }
            }
            Behavior on y{
                SmoothedAnimation{ duration: 500 }
            }
        }

QMLドキュメント全体で複数のidと同じ要素(HTMLのような)が同時にあることは許されていませんが、動的に作成されたコンテンツIDの属性は合法的です.
このグラフィックオブジェクトを作成する必要がある場合、create.createObject(parentNode)のこのQML関数を呼び出して、作成された要素のポインタを返します.同じオブジェクトを複数作成する場合は、作成したobjectをリストに保存して管理しやすくなります.
var obj = create.createObject(image,{});//       
list.push(obj)//       
カスタム属性をバインド
各QML要素のタイプは、予め定義された属性(例えばx,y,opacity)以外にも、私達がカスタマイズした属性を追加することができます.要素にバインディングの属性を追加するのも同じです.
Image{
    id: img
    x: 0
    y: 0
    property int maxNum: 15//        
    property var list: []//      
}
ノードにアクセスする属性は同じです.
img.maxNum = 15//    
バインディング属性は、例えばオブジェクトのアニメーションにおいて、x、y値の重複動作を避けるために、バインディング属性を使用して衝突を避けることができます.
データモデルを使う
QMLには、あらかじめ作成されたデータモデル、例えばListModelがあります.ListModelを使って、任意にListItemに基づくリストを作成できます.各要素はListItemであり、要素内部には多くの属性が含まれています.Cの構造体配列の典型的なListModel類のようです.
ListModel {
                            id:cpStateList
                            ListElement {
                                cpIndex:0
                                cpState: "  "
                                cpCurrentTime:0
                                cpNeedTime:0
                            }

                            ListElement {
                                cpIndex:1
                                cpState:  "  "
                                cpCurrentTime:0
                                cpNeedTime:0
                            }

                            ListElement {
                                cpIndex:2
                                cpState:  "  "
                                cpCurrentTime:0
                                cpNeedTime:0
                            }

                            ListElement {
                                cpIndex:3
                                cpState: "  "
                                cpCurrentTime:0
                                cpNeedTime:0
                            }
}
このように、データバインディングが必要な場合、リストのデータとListModelのListItemを一つずつバインディングしてもいいです.データを操作する必要がある場合、このような方法を使います.
var obj = cpStateList.get(Index)//   ListModel    Index   
obj.xxx = ???// xxx      
ListModelにはもう一つ重要な応用があります.前付けのViewの中にデータソースとして、対応するテンプレートにレンダリングします.例えば、GridViewは便利にグリッドビューを構築でき、各グリッドはdelegate(代表モデル)に基づく構造であり、構造中のデータは対応するmodel内部のデータを自動的に呼び出します.典型的なGridViewはこのようにしています.
GridView {

                        id: cpStateBoard
                        x: 56
                        y: 13
                        width: 894
                        height: 84
                        cellHeight: height
                        cellWidth: width/8

                        delegate: Item {
                            Column {
                                spacing: 30
                                    Text{
                                        x:0
                                        y:10
                                        text:cpState
                                        font.family: "Source Han Sans CN Normal"
                                    }

                                    Text {
                                        x: 0
                                        y: 30
                                        text: cpCurrentTime + '/' + cpNeedTime
                                        opacity: cpState == "  " ? 0 : 1
                                        font.family: "Source Han Sans CN Normal"
                                        //anchors.horizontalCenter: parent.horizontalCenter
                                    }
                                }
                            }
                        }
                        model: ListModel {
                            id:cpStateList
                            ListElement {
                                cpIndex:0
                                cpState: "  "
                                cpCurrentTime:0
                                cpNeedTime:0
                            }

                            ListElement {
                                cpIndex:1
                                cpState:  "  "
                                cpCurrentTime:0
                                cpNeedTime:0
                            }
}
使用するmodelの内部に二つのデータがあると、二つのグリッドにText要素があり、それぞれのグリッドの内部レイアウトとdelegateが一致して、ListElementの中の二つのデータをそれぞれ使用していることをレンダリングする.modelの操作によって、一つのグリッドは動的に削除され、統一されたフォーマットを維持することができます.
アニメーションの使用
一つの要素にアニメーションを追加するには主にいくつかの形式があります.
  • は、要素の中で完全なアニメーションを定義し、動きが必要な場合は
  • を呼び出す.
  • は、ある属性に結合した補間を与え、ある属性が変化したときに自動的に補間を行う
  • .
    よく使われているのは第二種類です.例えば、この画像が動きを滑らかに動かすことができればいいです.
        Rectangle {
            id: details
            opacity: 0
    
    
            Behavior on opacity{
                NumberAnimation{
                    duration: 200
                }
            }
    
            Behavior on x{
                SmoothedAnimation{
                    duration: 100
                }
            }
    
            Behavior on y{
                SmoothedAnimation{
                    duration: 100
                }
            }
        }
    
    このようにx、y値が変化すると、自動的にSmmoothedAnimationが実行され、100 msの長い時間を経て、この方法はopacity属性に結び付けられ、フェードアウトの効果が得られます.
    注意すべきことは、要素が運動中に彼のx,y属性を検査すると、現在の運動における値であり、最終値ではないことを発見することである.したがって、運動中に item.x -= 100 のような割当値を行わないようにしなければならない.さもなければ、最終的な位置は、最初の割当値−100ではなく、ある時点の位置−100に移動することになる.このような場合を避けるために、バインディング属性の方法、例えば(x,y属性に注意する)を使用してもよい.
    Image {
                id: tourist
                source: sprites[Math.floor((Math.random()*3))]
                width: 20
                height: 20
                property int x_axid: 1010
                property int y_axid: 120
                x:x_axid
                y:y_axid
                Behavior on x{
                    SmoothedAnimation{ duration: 500 }
                }
                Behavior on y{
                    SmoothedAnimation{ duration: 500 }
                }
            }
    
    位置を変えるたびにx_を変える.axid/y_axidの値はxであり、y属性はそれに伴って変化し、同時に動画を動きますが、運動中は item.x_axid -= 100 を行います.変化は依然として最終値-100です.
    QMLステップ
    最後に、QMLとHTMLは似ているところが多すぎて、QMLではどのように書けばいいのかわからない時でも、JavaScriptの書き方を試してみます.QMLでもMath.flor()、Number()、String()などの関数があります.