このページでは

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 ハンドラを、targetbutton に設定された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ライセンスの下で利用可能です。
詳細はこちら。