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という形式で記述されます。
例えば、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}`)
}注意: すべてのシグナル・パラメータは、ブロックのスコープに注入されます。
コネクション型の使用
シグナルを発するオブジェクトの外からシグナルにアクセスしたい場合があります。QtQuick モジュールは、任意のオブジェクトのシグナルに接続するための QML タイプConnections を提供します。Connections オブジェクトはそのtarget から任意のシグナルを受け取ることができます。
先ほどの例では、onClicked ハンドラのルートRectangle もシグナルを受け取ることができました。これは、target をbutton に設定したConnections オブジェクトの中にonClicked ハンドラを配置することで可能になります:
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の作成処理が完了したときに、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 attach タイプのオブジェクトが、QMLエンジンによって自動的にRectangle オブジェクトにアタッチされています。QMLエンジンはRectangleオブジェクトの生成時にこのシグナルを発行し、Component.onCompleted シグナルハンドラをトリガします。
シグナルハンドラがアタッチされることで、各オブジェクトにとって重要な特定のシグナルが通知されるようになります。例えば、Component.onCompleted アタッチド・シグナル・ハンドラがなかった場合、オブジェクトは、特別なオブジェクトからの特別なシグナルに登録することなく、この通知を受け取ることができませんでした。アタッチドシグナルハンドラ機構は、余分なコードを書かずにオブジェクトが特定のシグナルを受け取ることを可能にします。
アタッチドシグナルハンドラの詳細については、アタッチドプロパティとアタッチドシグナルハンドラを参照してください。
カスタムQML型へのシグナルの追加
signal 、カスタムQML型にシグナルを追加することができます。
新しいシグナルを定義するための構文は以下の通りです:
signal <name>[([<type> <parameter name>[, ...]])]
シグナルはそのシグナルをメソッドとして呼び出すことで発生します。
例えば、以下のコードはSquareButton.qml という名前のファイルで定義されています。ルートであるRectangle オブジェクトはactivated シグナルを持っており、子オブジェクトMouseArea がtapped になるたびにシグナルが発せられます。この例では、アクティブ化されたシグナルはマウスクリックの 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 ライセンスの下で利用可能です。
詳細を確認してください。