画像付きのQMLコンボボックスやリストを作るテクニック
Create a QML ComboBox / ListView with an image
QMLではComboBoxやListViewなどのリスト形式のアイテムは「ListModel」と呼ばれるデータをもとにして作成されます。
ListModeへはListElementアイテムにKey-Value形式のデータを追加していきます。通常は「text」のキーを持つデータが反映されますが、独自のテンプレートを用意することで、キーをもとに任意のデータを表示させることが可能です。
独自のキーを定義した場合は、表示のためのQMLを自前で作ります。コンボボックスでは、ComboBoxStyleというアイテム(import QtQuick.Controls.Styles 1.0)のlabelプロパティにQMLレイアウトを割り当てると反映されます。
このサンプルでは、コンボボックスのラベルに内部のアイテムを横に並べることのできる「Row」へ「Image」と「Text」を追加し、モデルに格納されている対象のデータを描画するようにしています。
imgcmb.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Image ComboBox")
ComboBox{
id: cb
width: 100
style: ComboBoxStyle{
id: cbstyle
label: Row{
// はみ出た部分は描画させない
clip:true
Image{
id:color
// ソースとして選択中インデックスのimgデータを使用
source:cbdata.get(cb.currentIndex).img
height:parent.height
width:this.height
// アイテム枠内に画像を縮小させる
fillMode: Image.PreserveAspectFit
}
Text{
id:text
text:cbdata.get(cb.currentIndex).text
anchors.verticalCenter: parent.verticalCenter
}
}
}
model: ListModel {
id: cbdata
ListElement { text: "Glape"; img:"imgs/icon1.png" }
ListElement { text: "Banana"; img:"imgs/icon2.png" }
ListElement { text: "Apple"; img:"imgs/icon3.png" }
}
}
}
なお、画像ファイルなどをリソースとしてプロジェクトに登録するには、プロジェクトのメニューより「既存のファイル/ディレクトリを追加」より、ファイルやフォルダを選択することで行えます。リソース内部で階層化した場合は、リソースの参照時も階層を明記します。
リストビューで独自のレイアウトを用いるにはdelegateプロパティにComponentアイテムを割り当てます。コンボボックスとは異なり、クリックして選択したり、アイテムのハイライト表示などの選択状態の処理はQMLで都度作成する必要があります。
listview.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("ListView")
ListView{
id: lv
model: lm
width: 100
height: 100
clip: true
// リスト描画の定義
delegate: user
// ハイライトの描画定義(水色の矩形を左右いっぱいに広げて配置)
highlight: Rectangle {
color: "#cde7ff"
anchors.left:parent.left
anchors.right:parent.right
}
}
Component{
// リストアイテムの定義
id:user
Item{
width: lv.width
height: 25
// アイテムをクリックできるようにする
MouseArea{
anchors.fill: parent
onClicked: {
// アイテムが保有するインデックスをリストに適用させることで、選択状態にさせる
lv.currentIndex = index;
}
}
Row{
anchors.fill: parent
Text{
id:f_name
text: name
}
Image{
id:f_icon
source: src
height:parent.height
fillMode: Image.PreserveAspectFit
}
CheckBox{
id:f_check
checked: chk
}
}
}
}
// リストアイテムの初期定義
ListModel{
id:lm
ListElement{
name: "User1"
src: "icon1.png"
chk: false
}
ListElement{
name: "User2"
src: "icon2.png"
chk: true
}
ListElement{
name: "User3"
src: "icon3.png"
chk: false
}
}
// アイテムを動的に追加する例
Button{
anchors.top: lv.bottom
text: "Add"
onClicked: {
lv.model.append({ name:"new", src:"icon1.png", chk:true });
}
}
}
2018/10/31