Qtのプロパティに関するノート  - Qtで作るAndroid目覚ましもどき #3-3 -

Qtで作るAndroid目覚ましもどきシリーズ３としてまず画面構成の話をします、の３回目。
今回は私の作った[プログラム](https://github.com/hakua-doublemoon/SummerIce)をより具体的に使っていきます。

# 目的/やりたいこと
目覚ましなのでまず時間の設定する何かととアラームの開始・停止をするボタン等が必要です。そのため下記のように画面を作ります。

```
+-----------------------+
| ApplicationWindow     |
|                       |
|     +--------------+  |
|     | 時間設定域    |  |
|     +--------------+  |
|                       |
|     +-----------+     |
|     | 開始ボタン |     |
|     +-----------+     |
|                       |
+-----------------------+
```
この時に画面が実現するべき最低限の機能は１つ。

* 「開始ボタン」を押したときに内部の制御ロジックに「時間設定域」で設定している時間を伝えたい

これを目的とした話にします。

# 方法/やり方
## その前に部品の配置をキメよう
……とだらだら書こうかと思ったけど公式の入門講座があるのでそちらを参照。
anchorの話も下記の"レイアウト"に書いてあるので読むと良いです。

* [Qt Quick 入門 第7回: レイアウト](https://blog.qt.io/jp/2011/01/06/qml-layout/)
* [Qt Quick 入門 第10回: プロパティバインディング](https://blog.qt.io/jp/2011/04/27/propertybinding/)

## 目的のためにはプロパティの参照の習得が必要
プロパティはQMLにおけるインスタンス変数やパラメータのようなものであり、簡単に使うだけなら適当に書いて適当に読み出せば何とかなるでしょう。しかし部品を階層化・モジュール化・別ファイル化していくと親子・兄弟でのプロパティのルールの壁にぶち当たります。
というわけで目的の一番の壁となりやすい親子・兄弟間でのプロパティの参照について書きます。これは教科書に書いてあるようで、少なくとも私の教科書ではわかりづらかったのでこうしてノートを起こします。
より具体的に問題を分割すると下記のようになります。

1. 子から親へのプロパティ参照
2. 孫（子の子）から親（祖父母）へのプロパティ参照
3. 親から子へのプロパティ参照
4. 親（祖父母）から孫へのプロパティ参照
5. 兄弟間のプロパティ参照
6. 叔父・叔母への参照
7. 甥・姪への参照

……人間の親族呼称でごめんなさい。

### レベル１
一番簡単なやつ。
1. 子から親へのプロパティ参照
2. 孫（子の子）から親（祖父母）へのプロパティ参照
これは親・祖父母が持っているプロパティをそのまま書けば良い。例えば下記。

``` main.qml
ApplicationWindow {
    // :
    readonly property int voice_name_box_added_width: 50
    // :
    Parts_hscroll_list {
        // :
        id: _chara_list
        x:  _toggles.x - voice_name_box_added_width/2
        y:  400
        // :
    }
    // :
}
```
親のApplicationWindowが持っている`voice_name_box_added_width`プロパティを`_chara_list`は直接参照しています。
孫でも同じようにできます。
ただし親と子で同じ名前のプロパティを持っている場合は注意が必要で、主にparentを使います。

``` main.qml
    Image {
        id: _bgImg
        height: parent.height
        // :
    }
```
祖父母のプロパティを使いたい場合は`parent.parent.`みたいに書きます。
parentと書くとわからなくなってくるときがあり、名指ししたいなーという時にidを使うこともできます。

### レベル２
まあレベル１と同じか。
3. 親から子へのプロパティ参照
5. 兄弟間のプロパティ参照
idで名指しにします。親の数は決まってますが子や兄弟の数は未知数なので。
親から子への参照については良い例がなかったので省略。兄弟間では下記。

``` main.qml
    // :
    Asm_toggles {
        id: _toggles
        x: 230
        y: 200
        // :
    }
    // :
    Parts_knocker {
        id: _knocker
        x:  _toggles.x
        y:  550
        // :
    }
    // :
```

### レベル３
4. 親（祖父母）から孫へのプロパティ参照
6. 叔父・叔母への参照
7. 甥・姪への参照

これが少し苦しむ。何故かというとこの関係にある人たちは互いのこと（名前＝id）を直接呼べないから。
正確には、同じファイルなら呼べる関係もあるがファイルが違うと呼べなくなる。大家族と核家族で親戚の距離間が変わるんですね。
孫を呼べないなら、子が親に自分の子のプロパティを見せる必要があると考えるなら、子が子のプロパティを自分のプロパティとして定義しなおします。
また必要に応じて計算した値で定義しなおすこともできます。
叔父・叔母と甥・姪についても同じです。
こうすることで兄弟や親子間での参照と同じレベルに問題を引き上げるのです。
下記の例は叔父・叔母―甥・姪の話になるでしょうか。（解析お願いします）

``` item/Asm_toggles.qml
Item {
    // :
    property int public_hour: _hour_top.public_num*10 + _hour_und.public_num
    property int public_min:  _min_top.public_num *10 + _min_und.public_num
    // :
        Parts_toggle {
            id: _hour_top
            public_is_arrow: true
            max_val: 2
            //onSigToggle: {}
        }
    // :
}
```
`Parts_toggle`オブジェクトの`_hour_top`が持つ`public_num`という値を`_hour_top`の兄弟の値と組み合わせて`public_hour`として定義しなおしています。
これを`Asm_toggles`オブジェクトの`_toggles`インスタンスの兄弟である`Parts_knocker`オブジェクトの`_knocker`インスタンスで下記のように使います。

``` item/Parts_knocker.qml
                _pongLabel.text = Ice.setAlerm(_toggles.public_hour, _toggles.public_min);
```

`Ice.setAlerm()`という関数を使うことが冒頭の目的に挙げた"内部の制御ロジックに「時間設定域」で設定している時間を伝えたい"を実現することになります。
よってこれで一応目的が達成されたことになりました。

#### alias
またaliasでも同じようにできます。

``` item/Asm_toggles.qml
Item {
    // :
    property alias ringingFlag: _ring_timer.running
    // :
    Timer {
        id: _check_time
    // :
    }
    // :
}
```

# 備考
* Loaderを使った動的に配置されるオブジェクトにおいてもプロパティの参照ルールは基本的に変わりません  
   ただしQt Creatorでは普通に置いているオブジェクトでは参照できるものは補完されたりしてそれと分かりますが、Loaderでの配置の関係はQt Creatorでは理解されないので動かして確認していったりすると思います
* 関数についても値のプロパティと同じようなルールで使えます。（関数にてついて説明してないですし説明する技量もないですが）

# 余談
* [Qtのリファレンス](http://doc.qt.io/qt-5/qtqml-syntax-objectattributes.html)を見たらちゃんと"Each instance of an object type"などインスタンスという表現が出てきてた。職場で勉強に使った本にはなかったが。というわけでインスタンスという言葉を理解しているかのようにどんどん使っていこうと思います。