Qt 5.12~14あたりの情報です。
#Qtのサンプルアプリがおかしい。
QtにはAlarmsというサンプルプロジェクトがついてきます。
AlarmsにはTumblerで年月日を設定するコードがあるのですが…。
なんか挙動がおかしいです。
年と月の設定によって日数を変更しているのですが、日数が変更されるたびに変な動きをします。
うるう年とかの設定もなんかいい加減です。
なので自分で作ってみました。
#Tumblerの実装
まずは以下のように年月日のTumblerを配置。
Text {
id: yearPrefix
text: "20"
color: "white"
anchors.verticalCenter: parent.verticalCenter
font{ pixelSize: 40 }
}
Tumbler {
id: yearTumbler
anchors.left: yearPrefix.right
anchors.verticalCenter: parent.verticalCenter
width: 50; height: 300
model: 100
delegate: tumblerDelegate
property int plus: 0
onMovingChanged: setDate()
}
Tumbler {
id: monthTumbler
anchors.left: yearTumbler.right
anchors.verticalCenter: parent.verticalCenter
width: 50; height: 300
model: 12
delegate: tumblerDelegate
property int plus: 1
onMovingChanged: setDate()
}
Tumbler {
id: dayTumbler
anchors.left: monthTumbler.right
anchors.verticalCenter: parent.verticalCenter
width: 50; height: 300
model: 31
delegate: tumblerDelegate
property int plus: 1
}
property int plusは、タンブラーの表示が0スタートなのか1スタートなのかを示しています。
年は00から始まってほしいけど、月と日は01から始まってほしいですからね。
この値は、次のtumblerDelegateで使います。
#続いてデリゲート
デリゲートは3つのタンブラー共通で、下記のものを使います。
Component {
id: tumblerDelegate
Text {
color: yearPrefix.color
opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
text: ("0" + (modelData + Tumbler.tumbler.plus)).slice(-2)
font: yearPrefix.font
verticalAlignment: Text.AlignVCenter
}
}
デリゲート中でTumbler.tumbler.plusと書くと、先ほどのproperty int plusを読むことができます。
#最後に日数を変更する関数
yearTumblerとmonthTumblerのmoving変更時に、下記の関数を呼んでます。
function setDate() {
if(!yearTumbler.moving && !monthTumbler.moving) {
var lastDay = new Date(2000+yearTumbler.currentIndex, monthTumbler.currentIndex+1, 0).getDate()
var currentDay = Math.min(dayTumbler.currentIndex, lastDay-1)
dayTumbler.model = lastDay
dayTumbler.positionViewAtIndex(currentDay, Tumbler.Center)
}
}
年月両方のTumblerが停止していたら、dayTumblerのmodelを変更して日数を変更します。
年月の最終日を取得するのに、new Date()を使っています。
Date(年, 月, 0)とすると、その年月の最終日を取得できます。
C++側で、QDate::daysInMonth()なんかを使っても良いですね。
3/31から2月に変更すると、2/28を示すようにcurrentDayを設定しています。
positionViewAtIndex()より先に、modelを変更することが必要です。
modelを変更するとcurrentIndexが0に戻るっぽいので。
(QtのAlarmsサンプルの挙動がいまいちおかしいのは、ここら辺の記述が適当だから。)
positionViewAtIndex()は、アニメーションすることなしにcurrentIndexを変更できます。
単純にcurrentIndexに代入すると、タンブラーがくるくる回ってしまうので。