📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

ページの作成:「== 概要 == ソフトウェアはデータを生成して、データを表示する必要がある。<br> Qt Quickには、データを表示するためのモデル、…」
 
編集の要約なし
 
(同じ利用者による、間の4版が非表示)
39行目: 39行目:
<br>
<br>
上記のビューには、それぞれ専用のプロパティと動作がある。<br>
上記のビューには、それぞれ専用のプロパティと動作がある。<br>
<br><br>
<br>
 
==== ビューの装飾 ====
== ビューの装飾 ==
ビューでは、<code>header</code>、<code>footer</code>、<code>section</code>等の装飾用プロパティを使用して、見た目をカスタマイズすることができる。<br>
ビューでは、<code>header</code>、<code>footer</code>、<code>section</code>等の装飾用プロパティを使用して、見た目をカスタマイズすることができる。<br>
<br>
<br>
128行目: 127行目:
<br>
<br>
[[ファイル:QML Model and View 2.png|フレームなし|中央]]
[[ファイル:QML Model and View 2.png|フレームなし|中央]]
<br><br>
<br>
 
==== マウスとタッチの操作 ====
== マウスとタッチの操作 ==
ビューは、コンテンツのドラッグやフリックを処理するが、個々のデリゲートとのタッチ操作は処理しない。<br>
ビューは、コンテンツのドラッグやフリックを処理するが、個々のデリゲートとのタッチ操作は処理しない。<br>
<br>
<br>
138行目: 136行目:
<u><code>highlightRangeMode</code>プロパティが<code>StrictlyEnforceRange</code>に設定されている場合、ビューは常に<code>currentIndex</code>プロパティが指定されたハイライト範囲内にあることを保証するため、</u><br>
<u><code>highlightRangeMode</code>プロパティが<code>StrictlyEnforceRange</code>に設定されている場合、ビューは常に<code>currentIndex</code>プロパティが指定されたハイライト範囲内にあることを保証するため、</u><br>
<u><code>currentIndex</code>プロパティはビューをドラッグおよびフリックしても影響を受けない。</u><br>
<u><code>currentIndex</code>プロパティはビューをドラッグおよびフリックしても影響を受けない。</u><br>
<br><br>
<br>
 
==== ListViewのセクション ====
== ListViewのセクション ==
<code>ListView</code>のコンテンツはセクションにグループ化されるため、関連するリストアイテムは、そのセクションに応じてラベル付けされる。<br>
<code>ListView</code>のコンテンツはセクションにグループ化されるため、関連するリストアイテムは、そのセクションに応じてラベル付けされる。<br>
また、セクションは、デリゲートを使用して装飾することもできる。<br>
また、セクションは、デリゲートを使用して装飾することもできる。<br>
201行目: 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>
==== 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>
QMLの<code>ListModel</code>はデフォルトで編集可能であるが、C++のモデルは<code>setData</code>メソッドを実装しないと編集できない。<br>
なお、整数やJavaScriptの配列モデルは、読み取り専用である。<br>
<br>
以下の例では、EditableModelは<code>QAbstractItemModel</code>を継承したC++モデルで<code>setData</code>メソッドを実装しており、かつ、QML型として登録されている場合、<br>
データは、以下のようにモデルに書き込まれまる。<br>
<syntaxhighlight lang="qml">
ListView {
    anchors.fill: parent
    model: EditableModel {}
    delegate: TextEdit {
      width: ListView.view.width
      height: 30
      text: model.edit
      Keys.onReturnPressed: {
          model.edit = text
      }
    }
}
</syntaxhighlight>
<br>
<u>※注意</u><br>
<u><code>edit</code>ロールは、<code>Qt::EditRole</code>と同じである。組み込みのロール名については、[https://doc.qt.io/qt-5/qabstractitemmodel.html#roleNames roleNames()]を参照すること。</u><br>
<u>実際のモデルでは、通常、カスタムロールを登録する。</u><br>
<br>
モデルのロールが<code>required <プロパティ名></code>にバインドされている場合、そのプロパティに割り当ててもモデルは変更されない。<br>
代わりに、モデルへのバインドが解除される。(他のプロパティへの割り当てが既存のバインドを解除するのと同様である)<br>
<br>
必須プロパティを使用してモデルデータを変更する場合、<code>model</code>も必須プロパティにして<code>model.propertyName</code>に割り当てる。<br>
<br>
詳細は、[https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html#changing-model-data Using C++ Models with Qt Quick Views]を参照すること。<br>
<br><br>
== トランジションの使用 ==
トランジションは、ポジショナに追加、ポジショナ内での移動、ポジショナから削除されたアイテムをアニメーション化するために使用する。<br>
<br>
アイテムを追加するトランジションは、ポジショナの一部として作成されたアイテムや、ポジショナの子になるために再配置されたアイテムに適用される。<br>
アイテムを削除するためのトランジションは、ポジショナ内のアイテムが削除された場合や、ポジショナから削除されてドキュメント内に新しい親が与えられた場合に適用される。<br>
<br>
<u>※注意</u><br>
<u>アイテムの不透明度をゼロに変更しても、ポジショナからアイテムが消えることはない。</u><br>
<u>これらのアイテムは、<code>visible</code>プロパティを変更することで、削除および追加することができる。</u><br>
<br><br>
<br><br>


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