Skip to content

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.alignmentText のプロパティではなく、コンポーネント毎に別の領域で管理される場所に LayoutAttached を生成して、それの .alignment を設定する。ここで (型名).(プロパティ名) となっているのが重要で、こういった形式なら付属オブジェクト、そうでなければ通常のプロパティとして扱われる。だから font.pizelSize はただのオブジェクトになるはず。

そうしておくと、画面の再レイアウトが必要になったとき、親コンテナの RowLayout が子の付属オブジェクトを参照し、それを使って描画を行うことができる。もちろん逆もあって、Text を再描画するときは、Text が付属プロパティで参照している値を親のコンテナが提供する。

では親コンポーネントが Layout でない場合はどうなるのかでいえば、QtQuick.Layout をインポートしているので付属オブジェクトは作成できるけれども、親コンポーネントがそれを参照しないので何も起きない、という動作になる。

共通するイベントを受け取る場合

Section titled “共通するイベントを受け取る場合”

KeysComponent 型の付属オブジェクトは、多くのコンポーネントで共通するイベントを受け取るために使える。例えば以下では TextArea がキーイベントを受け取っている。

TextArea {
Keys.onPressed: (event) => {
if(event.key === Qt.Key_Return){
postButton.clicked()
event.accepted = true
}
}
}

TextArea の型階層を辿っても、誰も pressed シグナルを提供していない。代わりに Keys 付属オブジェクトのプロパティとしてデリゲート関数を生成しておくと、キーイベントが発生したときにフォーカスのあるコンポーネントのイベントが発火するしくみとなっている。

TextArea はマウスイベントを受け取るための pressed シグナルを提供しているのだから、同じようにキーイベントのシグナルも受け取ればいいんじゃないかと思うが、そうなっていない。

利用可能な付属オブジェクトを探すためには、

  • 親コンポーネントのドキュメント、またはその祖先クラスのドキュメント
  • コンポーネント自身のドキュメント、または祖先クラスのドキュメント

を探すと付属ドキュメントとして記述があるかもしれない。レイアウト関連は親のコンポーネントに書かれているだろうし、共通イベントはコンポーネント自身のドキュメントに書かれていることが多い。例えば上で挙げた Layout 付属オブジェクトは、実際はQtQuick.Layouts.Layoutアイテムが実装している。またC++のコードでは QQuickLayoutAttached というクラス名で実装されている。