「QMLの基礎 - モデルとビュー」の版間の差分

ナビゲーションに移動 検索に移動
編集の要約なし
198行目: 198行目:
<br>
<br>
[[ファイル:QML Model and View 3.png|フレームなし|中央]]
[[ファイル:QML Model and View 3.png|フレームなし|中央]]
<br><br>
== ビューのデリゲート ==
ビューは、リストの中のアイテムを視覚的に表現するために、デリゲートが必要となる。<br>
<br>
ビューは、デリゲートにより定義されたテンプレートにしたがって、各アイテムのリストを生成する。<br>
モデル内のアイテムは、アイテムのプロパティだけでなく、インデックスのプロパティにもアクセスできる。<br>
[[ファイル:QML Model and View 4.png|フレームなし|中央]]
<br>
<syntaxhighlight lang="qml">
Component {  // delegate: <アイテム名> { を使用することもできる
    id: petdelegate
    Text {
      id: label
      font.pixelSize: 24
      text: index === 0 ? type + " (default)" : type
      required property int index
      required property string type
    }
}
</syntaxhighlight>
<br>
<br>
==== デリゲートからのビューやモデルへのアクセス ====
デリゲートがバインドされているビューは、<code>view</code>プロパティを介してデリゲートからアクセスできる。(例. <code>ListView.view</code>, <code>GridView.view</code>等)<br>
したがって、対応するモデルとそのプロパティは、<code>view.model</code>を通じて使用できる。(例. <code>ListView.view.model</code>, <code>GridView.view.model</code>等)<br>
<br>
さらに、モデルに定義されているシグナルやメソッドもアクセス可能である。<br>
例えば、複数のビューに同じデリゲートを使用したいが、装飾等の機能は各ビューごとに異なるものにする場合や他の異なる設定を各ビューのプロパティにする場合に活用できる。<br>
同様に、モデルの各プロパティにアクセスおよび表示することもできる。<br>
<br>
以下の例では、デリゲート内の1つのTextアイテムは、<code>ListModel</code>内のlanguageプロパティを表示している。<br>
また、デリゲート内の1つのTextアイテムの色は、<code>ListView</code>内のfruit_colorプロパティに依存している。<br>
<syntaxhighlight lang="qml">
Rectangle {
    width: 200
    height: 200
    ListView {
      model: fruitModel
      delegate: fruitDelegate
      anchors.fill: parent
      property color fruit_color: "green"
    }
    ListModel {
      id: fruitModel
      property string language: "en"
      ListElement {
          name: "Apple"
          cost: 2.45
      }
      ListElement {
          name: "Orange"
          cost: 3.25
      }
      ListElement {
          name: "Banana"
          cost: 1.95
      }
    }
    Component {
      id: fruitDelegate
      Row {
          id: fruit
          Text {
            text: " Fruit: " + name
            color: fruit.ListView.view.fruit_color
          }
          Text {
            text: " Cost: $" + cost
          }
          Text {
            text: " Language: " + fruit.ListView.view.model.language
          }
      }
    }
}
</syntaxhighlight>
<br><br>
== モデル ==
データは、デリゲートがバインドすることができる名前付きのデータロールを介してデリゲートに提供される。<br>
<br>
以下の例では、typeとageという2つのロールを持つListModel、および、これらのロールにバインドして値を表示するデリゲートを持つListViewを作成している。<br>
<syntaxhighlight lang="qml">
import QtQuick 2.15
Item {
    width: 200
    height: 250
    ListModel {
      id: myModel
      ListElement {
          type: "Dog"
          age: 8
      }
      ListElement {
          type: "Cat"
          age: 5
      }
    }
    Component {
      id: myDelegate
      Text { text: type + ", " + age }
    }
    ListView {
      anchors.fill: parent
      model: myModel
      delegate: myDelegate
    }
}
</syntaxhighlight>
<br>
ロールのアクセスをより細かく制御する場合、および、デリゲートをビュー外部で使用する場合は、以下のように記述する。<br>
<syntaxhighlight lang="qml">
required property <データ型> <プロパティ名>
</syntaxhighlight>
<br>
デリゲートに必須プロパティが含まれている場合、名前付きのロールは提供されない。<br>
代わりに、QMLエンジンは、まず、必須プロパティ名がモデルロールの名前と一致するかどうかをチェックして、一致する場合、その必須プロパティはモデルの対応する値にバインドされる。<br>
<syntaxhighlight lang="qml">
import QtQuick 2.15
Item {
    width: 200
    height: 250
    ListModel {
      id: myModel
      ListElement {
          type: "Dog"
          age: 8
          noise: "meow"
      }
      ListElement {
          type: "Cat"
          age: 5
          noise: "woof"
      }
    }
    component MyDelegate : Text {
      required property string type
      required property int age
      text: type + ", " + age
      // 間違った記述: Component.onCompleted: () => console.log(noise)
      // 必須プロパティであるnoiseがないため、ReferenceErrorが発生する
      // 必要プロパティが存在することで、スコープにノイズが注入されるのを防ぐことができる
    }
    ListView {
        anchors.fill: parent
        model: myModel
        delegate: MyDelegate {}
    }
}
</syntaxhighlight>
<br>
モデルのプロパティとデリゲートのプロパティの間に名前の衝突がある場合、代わりに修飾されたモデル名でロールにアクセスすることができる。<br>
<br>
例えば、モデル内とデリゲート内の両方に同名のプロパティが存在する時、<br>
デリゲート内のプロパティではなく、モデル内のプロパティを参照する場合、<code><モデルのID名>.<プロパティ名></code>と記述することにより参照できる。<br>
<br>
また、モデル内のインデックスを含む特別なインデックスロールもデリゲートで使用できる。<br>
<br>
<u>※注意</u><br>
<u>このインデックスは、アイテムがモデルから削除されると<code>-1</code>に設定されることに注意すること。</u><br>
<u>インデックスロールにバインドする場合、インデックスが<code>-1</code>になる可能性、つまり、アイテムが有効でなくなる可能性を考慮したロジックにする。</u><br>
<u>(通常、アイテムはすぐに破棄されるが、一部のビューでは<code>delayRemove</code>プロパティによりデリゲートの破棄を遅らせることができる)</u><br>
<br>
名前付きロールを持たないモデル(例. <code>ListModel</code>等)は、モデルデータロールによりデータが提供される。<br>
モデルデータロールは、1つのロールしか持たないモデルにも提供される。この場合、モデルデータロールには、名前付きロールと同じデータが含まれる。<br>
<br>
<u>※注意</u><br>
<u>モデルロール、モデルデータロール、インデックスロールにおいて、デリゲートが必須プロパティを含んでいる場合、プロパティ名が一致しなければアクセスできないことに注意する。</u><br>
<br>
QMLには、いくつかのデータモデルが用意されており、それらはQMLの組み込み型に含まれている。<br>
加えて、モデルはQt C++で作成することができ、そのモデルを<code>QQmlEngine</code>クラスを使用してQMLコンポーネントから利用することもできる。<br>
<br>
モデルの作成については、[[QMLの基礎 - モデルの作成]]や[[QMLの基礎 - QMLタイプの作成]]を参照すること。<br>
<br>
モデルからアイテムを配置する場合は、<code>Repeater</code>を使用することで実現できる。<br>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:Qt]]
[[カテゴリ:Qt]]

案内メニュー