Quickshellの付属オブジェクト(Attached Object)
Quickshellコンポーネントには付属オブジェクト(Attached Object)と呼ばれる仕組みがある。これは付属プロパティ(Attached Property)とも呼ばれる。おそらく型名だけの表記なら付属オブジェクトで、プロパティも含めると付属プロパティと呼ばれるのではないか。
付属オブジェクトは、必要に応じてコンポーネントの外に値を持つための仕組みで、主要なものでは次のような型がある。
- Component
- Keys, Drag
- Accessible
- ListView, GridView など各種View
- Layout
よくある使い方は次の通り。
- 親子コンポーネント間で値のやりとりを行う
- 多くのコンポーネントで共通するイベントを受け取る
[! Attention] 親子という表現が紛らわしいが、コンポーネント文脈ではネストしている様子を、クラス文脈では型の継承を意味する。
親子コンポーネント間で値の交換をする場合
Section titled “親子コンポーネント間で値の交換をする場合”まずは親子コンポーネントで値を交換する場合の例を挙げる。
import QtQuick.Layouts
RowLayout { Text { Layout.alignment: Qt.AlignRight text: "text" font.pixelSize: 12 }}ここで Layout.alignment は Text のプロパティではなく、コンポーネント毎に別の領域で管理される場所に LayoutAttached を生成して、それの .alignment を設定する。ここで (型名).(プロパティ名) となっているのが重要で、こういった形式なら付属オブジェクト、そうでなければ通常のプロパティとして扱われる。だから font.pizelSize はただのオブジェクトになるはず。
そうしておくと、画面の再レイアウトが必要になったとき、親コンテナの RowLayout が子の付属オブジェクトを参照し、それを使って描画を行うことができる。もちろん逆もあって、Text を再描画するときは、Text が付属プロパティで参照している値を親のコンテナが提供する。
では親コンポーネントが Layout でない場合はどうなるのかでいえば、QtQuick.Layout をインポートしているので付属オブジェクトは作成できるけれども、親コンポーネントがそれを参照しないので何も起きない、という動作になる。
共通するイベントを受け取る場合
Section titled “共通するイベントを受け取る場合”Keys や Component 型の付属オブジェクトは、多くのコンポーネントで共通するイベントを受け取るために使える。例えば以下では TextArea がキーイベントを受け取っている。
TextArea { Keys.onPressed: (event) => { if(event.key === Qt.Key_Return){ postButton.clicked() event.accepted = true } }}TextArea の型階層を辿っても、誰も pressed シグナルを提供していない。代わりに Keys 付属オブジェクトのプロパティとしてデリゲート関数を生成しておくと、キーイベントが発生したときにフォーカスのあるコンポーネントのイベントが発火するしくみとなっている。
TextArea はマウスイベントを受け取るための pressed シグナルを提供しているのだから、同じようにキーイベントのシグナルも受け取ればいいんじゃないかと思うが、そうなっていない。
どうやって探すのか
Section titled “どうやって探すのか”利用可能な付属オブジェクトを探すためには、
- 親コンポーネントのドキュメント、またはその祖先クラスのドキュメント
- コンポーネント自身のドキュメント、または祖先クラスのドキュメント
を探すと付属ドキュメントとして記述があるかもしれない。レイアウト関連は親のコンポーネントに書かれているだろうし、共通イベントはコンポーネント自身のドキュメントに書かれていることが多い。例えば上で挙げた Layout 付属オブジェクトは、実際はQtQuick.Layouts.Layoutアイテムが実装している。またC++のコードでは QQuickLayoutAttached というクラス名で実装されている。