QML 信号和处理程序事件系统

QML 具有信号和处理程序机制。当发出信号时,会调用相应的信号处理程序。

一、使用信号处理程序接收信号

要在为特定对象发出特定信号时接收通知,对象定义应声明一个名为 on<Signal> 的信号处理程序,其中 <Signal> 是信号的名称,首字母大写。信号处理程序应包含在调用信号处理程序时要执行的 JavaScript 代码。

例如,来自 Qt Quick Controls 模块的 Button 类型有一个 clicked 信号,只要单击按钮就会发出该信号。在这种情况下,用于接收此信号的信号处理程序应为 onClicked:

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);
        }
    }
}

1.1、属性更改信号处理程序

当 QML 属性的值发生变化时,会自动发出信号。 这种类型的信号是属性更改信号,这些信号的信号处理程序以 on<Property>Changed 的形式编写,其中 <Property> 是属性的名称,首字母大写

例如,TapHandler 类型的 pressed 属性:

import QtQuick

Rectangle 
{
    id: rect
    width: 100; height: 100

    TapHandler 
    {
        onPressedChanged: console.log("taphandler pressed?", pressed)
    }
}

1.2、信号参数

信号可能有参数。要访问这些,应该为处理程序分配一个函数。可以使用箭头函数和匿名函数。

示例:

// Status.qml
import QtQuick

Item
{
    id: myitem
    signal errorOccurred(message: string, line: int, column: int)
}
Status 
{
    onErrorOccurred: (mgs, line, col) => console.log(`${line}:${col}: ${msg}`)
}

注意:函数中形式参数的名称不必与信号中的名称匹配。

如果不需要处理所有参数,则可以省略尾随参数:

Status 
{
    onErrorOccurred: function (message) { console.log(message) }
}

不能遗漏前导参数,但是可以使用一些占位符名称来向读者表明它们并不重要:

Status 
{
    onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`)
}

可以使用纯代码块代替函数,但不鼓励使用。在这种情况下,所有信号参数都被注入到块的作用域中。但是,这会使代码难以阅读,因为不清楚参数的来源,并导致 QML 引擎中的查找速度变慢。 不推荐以这种方式注入参数,如果实际使用该参数会导致运行时警告。

1.3、使用连接类型

在某些情况下,可能需要访问发出它的对象之外的信号。为了这些目的,QtQuick 模块提供了 Connections 类型来连接到任意对象的信号。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() 
        {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

1.4、附加的信号处理程序

附加信号处理程序从附加类型而不是在其中声明处理程序的对象接收信号。

例如,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)
    }
}

QML 引擎自动将具有完成信号的 Component 附加类型的对象附加到 Rectangle 对象。创建 Rectangle 对象时,引擎会发出此信号,从而触发 Component.onCompleted 信号处理程序。

二、向自定义 QML 类型添加信号

可以通过 signal 关键字将信号添加到自定义 QML 类型。

定义新信号的语法是:

signal <name>[([<type> <parameter name>[, ...]])]

2.1、通过将信号作为方法调用来发出信号。

示例: 

// SquareButton.qml
import QtQuick

Rectangle 
{
    id: root

    signal activated(real xPosition, real yPosition)        //定义信号
    property point mouseXY
    property int side: 100
    width: side; height: side

    TapHandler 
    {
        id: handler
        onTapped: root.activated(root.mouseXY.x, root.mouseXY.y)    //发出信号
        onPressedChanged: root.mouseXY = handler.point.position
    }
}

现在 SquareButton 的任何对象都可以使用 onActivated 信号处理程序连接到激活的信号:

// myapplication.qml

SquareButton
 {
    onActivated: (xPosition, yPosition)=> console.log("Activated at " + xPosition + "," + yPosition)
}

三、将信号连接到方法和信号

信号对象有一个 connect() 方法来将信号连接到一个方法或另一个信号。当信号连接到方法时,只要发出信号,就会自动调用该方法。 这种机制使信号能够由方法而不是信号处理程序接收。

下面,使用 connect() 方法将 messageReceived 信号连接到三个方法:

import QtQuick

Rectangle 
{
    id: relay

    signal messageReceived(string person, string notice)

    Component.onCompleted: 
    {
        relay.messageReceived.connect(sendToPost)
        relay.messageReceived.connect(sendToTelegraph)
        relay.messageReceived.connect(sendToEmail)
        relay.messageReceived("Tom", "Happy Birthday")
    }

    function sendToPost(person, notice) 
    {
        console.log("Sending to post: " + person + ", " + notice)
    }
    function sendToTelegraph(person, notice) 
    {
        console.log("Sending to telegraph: " + person + ", " + notice)
    }
    function sendToEmail(person, notice) 
    {
        console.log("Sending to email: " + person + ", " + notice)
    }
}

使用 connect() 允许多个方法接收信号。此外,connect() 在将信号连接到动态创建的对象时很有用。

有一个对应的 disconnect() 方法用于移除连接的信号:

Rectangle 
{
    id: relay
    //...

    function removeTelegraphSignal() 
    {
        relay.messageReceived.disconnect(sendToTelegraph)
    }
}

3.1、信号到信号连接

通过将信号连接到其他信号,connect() 方法可以形成不同的信号链。

import QtQuick

Rectangle 
{
    id: forwarder
    width: 100; height: 100

    signal send()
    onSend: console.log("Send clicked")

    TapHandler 
    {
        id: mousearea
        anchors.fill: parent
        onTapped: console.log("Mouse clicked")
    }

    Component.onCompleted: 
    {
        mousearea.tapped.connect(send)    //    信号连接到信号
    }
}

每当 TapHandler 的 tapped 信号发出时,send() 信号也将自动发出。输出:

    MouseArea clicked

    Send clicked

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QML中,获取系统位置权限可以通过使用Qt位置服务库(QGeoPositionInfoSource)来实现。以下是获取系统位置权限的步骤: 1. 导入位置服务库:在QML文件的开头添加以下语句: ``` import QtPositioning 5.15 ``` 2. 创建QGeoPositionInfoSource实例:使用以下代码创建一个QGeoPositionInfoSource对象并设置其属性: ``` PositionSource { id: positionSource active: true requestPermission: PositionSource.PermissionMode.PermissionModeAuto } ``` 在上述代码中,PositionSource是一个QML组件,通过设置active属性为true,启用位置服务。设置requestPermission属性为PermissionModeAuto,表示自动请求位置权限。 3. 监听位置更新:QGeoPositionInfoSource会发出位置更新信号,我们可以通过监听该信号来获取位置信息。例如,可以使用以下代码来获取经度和纬度: ``` onPositionChanged: { var position = positionSource.position; if (position.coordinate.isValid) { var latitude = position.coordinate.latitude; var longitude = position.coordinate.longitude; // 在这里使用位置信息进行相关操作 } } ``` 4. 请求权限:当第一次尝试获取位置信息时,系统通常会弹出一个权限对话框来询问用户是否允许应用程序访问位置。用户可以选择允许或拒绝。如果权限被拒绝,应用程序需要相应地处理。可以通过以下代码来检查权限状态: ``` if (positionSource.error === PositionSource.NoError) { // 获取位置权限成功 } else if(positionSource.error === PositionSource.PermissionError) { // 权限被拒绝 } else { // 其他错误 } ``` 通过以上步骤,我们可以在QML中获取系统位置权限,并使用获取的位置信息进行进一步的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值