前回の「QML(Qt)でチェックボックスを作る」を使って作ります。
ついでにグループボックスも作りました。
/// 今回のポイント ///
・初期表示時の選択アイテムを選べるようにした
・Repeaterを使ってListModelで内容を定義するだけでCheckBoxの配置を簡単にできるようにした
・childrenはRepeaterには定義されないのでColumnのを使用する
・Columnのchildere配列にRepeaterも含まれるので注意
・ListModelのパラメータに「_key」を追加して項目を一意に表現できるようにした
Repeaterのchilderenにはオブジェクトは配置されずにColumnに配置されてました。
その際、Repeater自身もColumnのchildrenに含まれるので注意です。
場所的にはリストの最後に居たので子供の数を「-1」しておけば扱い的にはなんとかなります。
ListModelのListElementのパラメータに「_key」を追加して一意に設定しておくと項目の数を増やしたり順番を入れ替えたりした時のデグレを防げますし可読性があがります。
上位のプログラムで選択された項目を振り分ける時のswitch文とかが楽ですよね。
#define的な物がなくて定数化がやりにくいので結構大事かなと思います。
(実はあるのかな?誰かいい方法教えてください)
各チェックボックスはColumnを使用して配置しているのでGridやRowを使えば並べ方もバリエーション作れます。
使用するときはonKeyChangedイベントで項目の選択変更を拾うのが良いと思います。
インデックスもキーもどちらも変更されて新しい状態になっています。
すぐわかりますがグループボックスはちょっと弱点があります。
文字の背景を透過させれません。
/// スクリーンショット ///
サンプルコードを実行した時のものです。
/// サンプルコード ///
まず呼び出し側のサンプル
// main.qml
import QtQuick 1.0
import "Components"
Rectangle {
width: 360
height: 360
Column{
anchors.fill: parent
anchors.margins: 5
spacing: 5
// グループボックス
GroupBox{
text: "Radio box test"
radius: 5
height: _radio.height + textHeight * 1.5
// ラジオボックス
RadioBox{
id: _radio
currentIndex: 1 // 選択の初期位置変更
anchors.top: parent.top
anchors.margins: parent.textHeight * 1.2
anchors.left: parent.left
anchors.leftMargin: 5
// 項目の設定
model: RadioBoxModel{
}
// 項目が変更された時のイベント
// こっちが先に呼ばれる(まだキーは変更されてない)
onCurrentIndexChanged: {
console.debug("onCurrentIndexChanged::"
+ "index=" + currentIndex
+ ", text=" + items[currentIndex].text
+ ", text=" + getCurrentItemText()
+ ", count=" + getItemCount()
+ ", key=" + currentKey);
}
// 項目が変更されてキーが変更された時のイベント
// こっちが後に呼ばれる
onCurrentKeyChanged: {
console.debug("onKeyChanged::"
+ "index=" + currentIndex
+ ", text=" + items[currentIndex].text
+ ", text=" + getCurrentItemText()
+ ", count=" + getItemCount()
+ ", key=" + currentKey);
}
}
}
}
}
ラジオボックスの内容を定義するモデル
// RadioBoxModel.qml
import QtQuick 1.0
ListModel {
ListElement {
_key: 0
_text: "CheckBox0"
}
ListElement {
_key: 1
_text: "CheckBox1"
}
ListElement {
_key: 2
_text: "CheckBox2"
}
ListElement {
_key: 3
_text: "CheckBox3"
}
}
ラジオボックス本体のコード
// RadioBox.qml
import QtQuick 1.0
Item {
id: _root
width: _items.width
height: _items.height
property int currentKey: 0 // 現在のアイテムのmodelで指定されたキー(読込み専用)
property int currentIndex: 0 // 現在の選択アイテムのインデックス
property alias items: _items.children // checkboxのリスト
property alias itemSpacing: _items.spacing // アイテム同士の間隔
property alias model: _itemsRepeater.model
// 読込み完了時の処理
Component.onCompleted: {
// 初期位置を設定する
if(currentIndex < 0 || currentIndex >= getItemCount()){
currentIndex = 0;
}
_items.children[currentIndex].checked = true;
currentKey = _itemsRepeater.model.get(currentIndex)._key;
}
// 含まれるcheckboxの数
function getItemCount(){
// Repeaterの分を引く
return _items.children.length - 1;
}
// 現在選択されているアイテムのテキスト
function getCurrentItemText(){
return _items.children[currentIndex].text;
}
// 自分以外のチェックを外す
function itemClicked(index){
for(var i=0; i< getItemCount(); i++){
if(i == index){
// 自分自身はなにもしない
}else{
// 自分以外のチェックを外す
_items.children[i].checked = false;
}
}
}
// 実際の内容
Column{
id: _items
spacing: 5
// リピータでお手軽配置
// modelは外から指定する
// _key は一意にすること
// _text は表示したい文字列
Repeater {
id: _itemsRepeater
delegate: CheckBox{
id: _item
text: _text
property int key: _key
onClicked: {
//インデックスなどを更新する
currentIndex = index;
currentKey = key;
// 自分以外のチェックを外す
itemClicked(index);
}
}
}
}
}
天の声があったので少し修正。itemClickedの引数をindexだけに変更。
delgateの中では「index」が使えるそうです。
おまけ的なグループボックス
// GroupBox.qml
import QtQuick 1.0
Item {
width: parent.width
height: parent.height
property alias text: _text.text // 表示するメッセージ
property alias color: _text.color // 色
property alias fontPointSize: _text.font.pointSize // フォントサイズ
property alias textHeight: _text.height // テキストの高さ
property alias textBkColor: _textArea.color // テキストの背景色
property alias radius: _border.radius // 角
property color borderColor: "#999999" // 枠の色
property int borderWidth: 1 // 枠の太さ
// 枠線
Rectangle {
id: _border
x: 0
y: _text.height / 2
width: parent.width
height: parent.height - y
border.color: borderColor
border.width: borderWidth
}
// タイトル
Rectangle {
id: _textArea
width: _text.width
height: _text.height
anchors.top: parent.top
anchors.left: parent.left
anchors.leftMargin: 5
color: "#ffffff"
Text{
id: _text
text: "Title"
}
}
}
コメント