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

402行目: 402行目:
<br>
<br>
モデルからアイテムを配置する場合は、<code>Repeater</code>を使用することで実現できる。<br>
モデルからアイテムを配置する場合は、<code>Repeater</code>を使用することで実現できる。<br>
<br>
==== ListModel ====
<code>ListModel</code>は、QMLで指定された単純な型の階層である。<br>
利用可能な役割は、<code>ListElement</code>プロパティで指定する。<br>
<syntaxhighlight lang="qml">
ListModel {
    id: fruitModel
    ListElement {
      name: "Apple"
      cost: 2.45
    }
    ListElement {
      name: "Orange"
      cost: 3.25
    }
    ListElement {
      name: "Banana"
      cost: 1.95
    }
}
</syntaxhighlight>
<br>
上記の<code>ListModel</code>は、nameロールとcostロールの2つのロールを持っている。<br>
これらは、例えば、<code>ListView</code>のデリゲートでバインドすることができる。<br>
<syntaxhighlight lang="qml">
ListView {
    anchors.fill: parent
    model: fruitModel
    delegate: Row {
      Text {
          text: "Fruit: " + name
      }
      Text {
          text: "Cost: $" + cost
      }
    }
}
</syntaxhighlight>
<br>
<code>ListModel</code>には、JavaScriptから<code>ListModel</code>を直接操作するためのメソッドが用意されている。<br>
この時、最初に挿入されたアイテムが、モデルを使用している全てのビューで利用可能なロールを決定する。<br>
<br>
例えば、空の<code>ListModel</code>があり、JavaScript経由で入力された場合、最初の挿入によって提供されたロールがビューに表示される唯一のロールとなる。<br>
<br>
以下の例では、初めて<code>MouseArea</code>の場所が押下する時、fruitModel(<code>ListModel</code>)にはcostロールとnameロールの2つのロールが追加される。<br>
次のロールが追加された場合も、モデルを使用するビューでは、最初の2つのロールのみが処理される。<br>
<br>
モデルで利用可能なロールをリセットするには、<code>ListModel::clear</code>メソッドを呼び出す必要がある。<br>
<syntaxhighlight lang="qml">
ListModel {
    id: fruitModel
}
// ...略
MouseArea {
    anchors.fill: parent
    onClicked: {
      fruitModel.append({"cost": 5.95, "name":"Pizza"})
    }
}
</syntaxhighlight>
<br>
==== XmlListModel ====
<code>XmlListModel</code>では、XMLデータソースからモデルを構築することができる。<br>
ロールは、<code>XmlRole</code>型で指定する。<br>
<br>
<code>XmlListModel</code>は、以下のモジュールをインポートする必要がある。<br>
<syntaxhighlight lang="qml">
import QtQuick.XmlListModel 2.15
</syntaxhighlight>
<br>
以下の例では、タイトル、リンク、説明の3つのロールを持っている。<br>
<code>query</code>プロパティは、<code>XmlListModel</code>がXMLドキュメント内の各<code><item></code>エレメントに対して、モデルアイテムを生成することを指定する。<br>
<syntaxhighlight lang="qml">
XmlListModel {
    id: feedModel
    source: "http://rss.news.yahoo.com/rss/oceania"
    query: "/rss/channel/item"
    XmlRole {
      name: "title"
      query: "title/string()"
    }
    XmlRole {
      name: "link"
      query: "link/string()"
    }
    XmlRole {
      name: "description"
      query: "description/string()"
    }
}
</syntaxhighlight>
<br>
[https://doc.qt.io/qt-5/qtdoc-demos-rssnews-example.html RSSニュースのデモ]では、<code>XmlListModel</code>を使用してRSSフィードを表示する方法を記載している。<br>
<br>
==== ObjectModel ====
<code>ObjectModel</code>は、ビューで使用されるビジュアルアイテムを含んでいる。<br>
<code>ObjectModel</code>をビューで使用する場合、<code>ObjectModel</code>には既に視覚的なデリゲート(アイテム)が含まれているため、ビューはデリゲートを必要としない。<br>
<br>
以下の例では、3つの色付きの長方形を<code>ListView</code>に配置している。<br>
<syntaxhighlight lang="qml">
import QtQuick 2.15
import QtQml.Models 2.15
Rectangle {
    ObjectModel {
      id: itemModel
      Rectangle {
          height: 30
          width: 80
          color: "red"
      }
      Rectangle {
          height: 30
          width: 80
          color: "green"
      }
      Rectangle {
          height: 30
          width: 80
          color: "blue"
      }
    }
    ListView {
      anchors.fill: parent
      model: itemModel
    }
}
</syntaxhighlight>
<br>
==== 整数型モデル ====
整数は、ある数の型を含むモデルとして使用できる。<br>
この場合、モデルにはデータの役割はありません。<br>
<br>
以下の例では、5つの要素を持つ<code>ListView</code>を作成している。<br>
<br>
<u>※注意</u><br>
<u>整数モデルのアイテム数の制限は、100,000,000であることに注意すること。</u><br>
<syntaxhighlight lang="qml">
Item {
    width: 200
    height: 250
    ListView {
      anchors.fill: parent
      model: 5
      delegate: itemDelegate
    }
    Component {
      id: itemDelegate
      Text {
          text: "I am item number: " + index
      }
    }
}
</syntaxhighlight>
<br>
==== C++データモデル ====
C++でモデルを定義して、それをQMLで使用することができる。<br>
この仕組みは、既存のC++データモデルや複雑なデータセットをQMLに公開するのに便利である。<br>
<br>
詳細は、[https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html Using C++ Models with Qt Quick Views]の記事を参照すること。<br>
<br><br>
== Repeater ==
<code>Repeater</code>は、モデルのデータをもとに、ポジショナで使用するアイテムをテンプレートから作成する。<br>
<code>Repeater</code>とポジショナを組み合わせることで、多くのアイテムを簡単に並べることができる。<br>
<br>
<code>Repeater</code>はポジショナの中に配置されて、ポジショナが配置したアイテムを生成する。<br>
<br>
各<code>Repeater</code>は、モデルのプロパティで指定されたモデルのデータの各要素、および、<code>Repeater</code>内の子アイテムとして定義されたテンプレートアイテムを組み合わせて、多数のアイテムを作成する。<br>
アイテムの総数は、モデルのデータ量によって決まる。<br>
<br>
以下の例では、<code>Grid</code>内で<code>Repeater</code>を使用して、<code>Rectangle</code>を格子状に配置している。<br>
<code>Repeater</code>は、<code>Grid</code>が5x5の配列で配置しており、計24個の<code>Rectangle</code>を作成している。<br>
<syntaxhighlight lang="qml">
import QtQuick 2.15
Rectangle {
    width: 400
    height: 400
    color: "black"
    Grid {
      x: 5
      y: 5
      rows: 5
      columns: 5
      spacing: 10
      Repeater {
          model: 24
          Rectangle {
            width: 70
            height: 70
            color: "lightgreen"
            Text {
                text: index
                font.pointSize: 30
                anchors.centerIn: parent
            }
          }
      }
    }
}
</syntaxhighlight>
<br>
<code>Repeater</code>が作成するアイテムの数は<code>Repeater.count</code>プロパティで保持されるが、このプロパティは読み込み専用のため設定することができない。<br>
そのため、上記の例のように、<code>Repeater.model</code>プロパティにアイテムの数を設定する。<br>
<br>
モデルが文字列リストの場合、デリゲートは文字列を保持する読み取り専用の<code>Repeater.modelData</code>プロパティにも保持される。<br>
以下の例では、<code>Repeater.model</code>プロパティのリスト配列を<code>Text.text</code>プロパティに順に設定して、<code>Text</code>を配置している。<br>
[[ファイル:QML Model and View 5.png|フレームなし|中央]]
<syntaxhighlight lang="qml">
Column {
    Repeater {
      model: ["apples", "oranges", "pears"]
      Text {
          text: "Data: " + modelData
      }
    }
}
</syntaxhighlight>
<br>
また、<code>Repeater</code>が作成するアイテムのテンプレートとして、デリゲートを使用することもできる。<br>
これは、<code>delegate</code>プロパティで指定する。<br>
<br><br>
<br><br>


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