C
シグナルとハンドラによるイベントシステム
アプリケーションとユーザーインターフェースのコンポーネントは、互いに通信する必要があります。たとえば、ボタンはユーザーがいつクリックしたかを把握する必要があります。ボタンは、その状態を示すために色を変更したり、何らかのロジックを実行したりすることがあります。さらに、アプリケーションはユーザーがボタンをクリックしたかどうかを知る必要があります。アプリケーションは、このクリックイベントを他のアプリケーションに伝達する必要がある場合があります。
QMLにはシグナルとハンドラの仕組みがあり、ここでシグナルはイベントそのものであり、シグナルはシグナルハンドラを通じて応答を受け取ります。シグナルが発信されると、対応するシグナルハンドラが呼び出されます。スクリプトやその他の操作などのロジックをハンドラ内に配置することで、コンポーネントはイベントに応答できるようになります。
シグナルハンドラによるシグナルの受信
オブジェクトの特定のシグナルに関する通知を受信するには、オブジェクト定義でon<Signal> という名前のシグナルハンドラを宣言する必要があります。ここで、<Signal> はシグナルの名前であり、最初の文字は大文字にします。シグナルハンドラではJavaScriptコードを使用する必要があり、このコードはシグナルハンドラが呼び出されるたびに実行されます。
Button たとえば、 Qt Quick Ultralite Controls モジュールの `clicked ` 型は、ボタンがクリックされるたびに ` ` シグナルを放出します。このシグナルを受信するための対応するシグナルハンドラは `onClicked` である必要があります。次の例では、ボタンがクリックされるたびに `onClicked ` ハンドラを呼び出し、親要素 `Rectangle` にランダムな色を適用しています:
import QtQuick import QtQuick.Controls Rectangle { id: rect width: 250; height: 250 Button { anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter text: "Change color!" onClicked: { rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1); } } }
注: シグナルハンドラはJavaScriptの関数に少し似ていますが 、直接呼び出してはいけません。シグナルハンドラと他の機能の間でコードを共有する必要がある場合は、それを別の関数にリファクタリングしてください。別の方法として、シグナルハンドラを呼び出すために常にシグナルを発行することもできます。同じシグナルに対して、異なるスコープで複数のハンドラを定義することができます。
プロパティ変更シグナルのハンドラ
プロパティ変更シグナルは、QMLプロパティの値が変更された際に発火します。このようなシグナルのハンドラはon<Property>Changed の形式で記述します。ここで、<Property>はプロパティ名であり、最初の文字は大文字にします。
たとえば、MouseArea 型にはpressed というプロパティがあります。このプロパティが変更されるたびに通知を受け取るには、onPressedChanged という名前のシグナルハンドラを記述します:
import QtQuick Rectangle { id: rect width: 100; height: 100 MouseArea { onPressedChanged: console.log("MouseArea pressed?", pressed) } }
MouseArea のドキュメントには「onPressedChanged 」という名前のシグナルハンドラに関する記述はありませんが、「pressed 」というプロパティが存在すること自体によって、このシグナルは暗黙的に提供されています。
シグナルのパラメータ
シグナルにはパラメータを指定できます。これらにアクセスするには、ハンドラに関数を割り当てる必要があります。
以下の例では、errorOccurred シグナルを持つStatus コンポーネントを想定します。
// Status.qml import QtQuick Item { id: myitem signal errorOccurred(message: string, line: int, column: int) }
Status { onErrorOccurred: console.log(`${line}:${column}: ${message}`) }
注:すべての シグナルパラメータは、ブロックのスコープに注入されます。
Connections タイプの使用
場合によっては、シグナルを発行するオブジェクトの外部からそのシグナルにアクセスしたいことがあります。「QtQuick 」モジュールでは、任意のオブジェクトのシグナルに接続するための「Connections 」QML型が提供されています。「Connections 」オブジェクトは、その「target 」から任意のシグナルを受信できます。
先の例では、onClicked ハンドラ内のルートRectangle もシグナルを受信することができました。これは、onClicked ハンドラを、target がbutton に設定されたConnections オブジェクト内に配置することで可能になります:
import QtQuick import QtQuick.Controls Rectangle { id: rect width: 250; height: 250 Button { id: button anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter text: "Change color!" } Connections { target: button function onClicked(event: MouseEvent) { rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1); } } }
アタッチされたシグナルハンドラ
アタッチされたシグナルハンドラは、ハンドラが宣言されているオブジェクトではなく、アタッチ元となる型からシグナルを受信します。
たとえば、Component.onCompleted はアタッチされたシグナルハンドラです。これは、その作成プロセスが完了した際に、何らかのJavaScriptコードを実行するためによく使用されます。以下に例を示します:
import QtQuick Rectangle { width: 200; height: 200 color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1) Component.onCompleted: { console.log("The rectangle's color is", color) } }
onCompleted ハンドラは、Rectangle 型からのcompleted シグナルには反応しません。その代わりに、completed シグナルを持つComponent アタッチング型のオブジェクトが、QMLエンジンによって自動的にRectangle オブジェクトにアタッチされています。エンジンはRectangleオブジェクトが作成された際にこのシグナルを発行し、それによってComponent.onCompleted シグナルハンドラがトリガーされます。
アタッチされたシグナルハンドラにより、各オブジェクトにとって重要な特定のシグナルについて、オブジェクトに通知を行うことが可能になります。たとえば、Component.onCompleted というアタッチされたシグナルハンドラが存在しなかった場合、オブジェクトは特定のオブジェクトからの特別なシグナルを登録しない限り、この通知を受け取ることができませんでした。アタッチされたシグナルハンドラの仕組みにより、オブジェクトは追加のコードを記述することなく、特定のシグナルを受け取ることができます。
アタッチされたシグナルハンドラに関する詳細については、「アタッチされたプロパティ」および「アタッチされたシグナルハンドラ」を参照してください。
カスタム QML タイプへのシグナルの追加
signal キーワードを使用することで、カスタムQML型にシグナルを追加できます。
新しいシグナルを定義するための構文は次のとおりです。
signal <name>[([<type> <parameter name>[, ...]])]
シグナルは、メソッドとしてそのシグナルを呼び出すことで発火されます。
たとえば、以下のコードは「SquareButton.qml 」という名前のファイルに定義されています。ルートオブジェクト `Rectangle ` には `activated ` シグナルがあり、子オブジェクト `MouseArea ` が `tapped` になったときに発火します。この具体的な例では、`activated` シグナルはマウスクリック時の x 座標と y 座標とともに発火します:
// SquareButton.qml import QtQuick Rectangle { id: root signal activated(real xPosition, real yPosition) property point mouseXY property int side: 100 width: side; height: side MouseArea { id: handler onPressed: { rect.mouseXY = Qt.point(mouseX, mouseY) rect.activated(rect.mouseXY.x, rect.mouseXY.y) } } }
これで、SquareButton のどのオブジェクトでも、onActivated シグナルハンドラを使用してactivated シグナルに接続できるようになります:
// myapplication.qml SquareButton { onActivated: console.log(`Activated at {xPosition}, ${yPosition}`) }
カスタムQML型用のシグナル作成に関する詳細については、「シグナルの属性」を参照してください。
特定のQtライセンスの下で利用可能です。
詳細はこちら。