LoginSignup
1
0

More than 3 years have passed since last update.

年月日の設定をQMLのTumblerで実装する

Posted at

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に代入すると、タンブラーがくるくる回ってしまうので。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0