您当前的位置: 首页 > 

龚建波

暂无认证

  • 4浏览

    0关注

    312博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

QML中的信号槽(信号与信号处理程序)

龚建波 发布时间:2019-02-26 21:53:55 ,浏览量:4

前言

信号和槽(signals & slots)是Qt框架的核心机制,Qt C++中的槽函数对应QML中的信号处理程序(signal handler)。

信号是事件(event),信号通过信号处理程序响应。发出信号时,将调用相应的信号处理程序。在处理程序中放置诸如脚本或其他操作之类的逻辑允许组件响应事件。

第一个例子:信号处理程序
//以下所有示例都在Qt5.9.7下测试
import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id: root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MouseArea {
        anchors.fill: parent
        //按键点击的信号处理程序
        onClicked: {
            console.log("on clicked");
        }
    }    
}

如例子所示,若要接收特定对象发出的特定信号,对象定义应声明一个名on的信号处理程序,其中是信号的名称,首字母大写。信号处理程序应包含在调用信号处理程序时要执行的JavaScript代码。

当MouserArea的clicked信号触发,onClicked处理程序就会被调用。

第二个例子:自定义信号及触发

除了处理预定义的信号,还可以自己定义和触发信号。

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id:root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    
    Rectangle{
        id:rect
        anchors.fill: parent
        color: "green"
        //自定义属性
        property int click_counts: 0
        //自定义信号 --无参信号可以省略括号
        signal signalA
        signal signalB(string str,int value)
        
        MouseArea {
            anchors.fill: parent           
            onClicked: {
                //按键点击,计数加一
                rect.click_counts++;
                //调用函数的形式来触发信号
                rect.signalB("signal counts",rect.click_counts);
                if(rect.click_counts%5===0){
                    rect.signalA(); //点击五次触发
                }
            }
        }
        //信号处理函数
        onSignalA: {
            console.log("click 5");
        }
        onSignalB: {
            //可以直接使用形参变量名
            console.log(str,value);
        }
    }
}

可以发现定义一个信号很简单,使用signal关键字就行了:signal [([ [, ...]])]

在Qt C++通过emit来发射信号,而在QML中直接将声明的信号当作函数来调用就可以触发了。而在信号处理函数中,可以使用声明中的变量名来获取对应的参数,如clicked信号带一个mouse参数,可以访问他获取点击时坐标等信息。

第三个例子:属性改变信号

在QML中,当属性(property)值改变时,会自动触发信号。

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id:root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")
    property int counts: 0

    //预定义属性改变
    onHeightChanged: {}
    //自定义属性改变
    onCountsChanged: {
        console.log("click counts",counts);
    }

    MouseArea {
        anchors.fill: parent
        //修改属性,触发信号
        onClicked: root.counts++
    }
}

属性改变信号处理程序以onChanged的形式关联,是属性的名称,首字母大写。

第四个例子:附加信号处理程序

一个附加信号处理程序是从接收信号的信号处理程序附加类型(attaching type)而不是在其内的处理程序被声明的对象。

例如,Component.onCompleted是附加的信号处理程序。此处理程序通常用于在其创建过程完成时执行某些JavaScript代码。

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id:root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Rectangle {
        id:rect
        anchors.fill: parent
        color: "yellow"

        focus: true
        //附加属性
        Keys.enabled: true
        //附加信号处理程序
        Keys.onPressed: {
            if(event.key===Qt.Key_0)
                console.log("key 0 pressed");
        }
        //附加信号处理程序
        Component.onCompleted: {
            //创建完成时执行
            console.log("color is", color)
        }
    }
}

附加属性的语法格式为:.

附加信号处理程序的语法格式为:.on

要了解更多的附加类型相关,可以查看文档。

第五个例子:连接任意对象的信号

在某些情况下,可能需要访问发射它的对象外部的信号(In some cases it may be desirable to access a signal outside of the object that emits it.)。出于这些目的,QtQuick模块提供Connections类型以连接任意对象的信号。一个Connections对象可以接收来自它的指定目标(target)的任何信号。

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id:root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Rectangle {
        id:rect
        anchors.fill: parent
        color: "yellow"

        MouseArea {
            id:mouse_area
            anchors.fill: parent
        }

        Connections{
            target: mouse_area
            //在外部连接MouseArea的点击信号
            onClicked:{
                console.log("clicked");
            }
        }
    }
}
第六个例子:信号到方法/信号的连接

信号对象具有connect()将信号连接到方法或另一信号的方法。当信号连接到方法时,无论何时发出信号,都会自动调用该方法。该机制使得能够通过方法而不是信号处理器来接收信号。可以一个信号connect()多个方法,并且可以对动态创建的对象使用connect()。亦可以使用disconnect()方法来取消关联。

import QtQuick 2.9
import QtQuick.Window 2.2

Window {
    id:root
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Rectangle {
        id:rect
        anchors.fill: parent
        color: "purple"
        signal signalA(string str)
        signal signalB(string str)

        MouseArea {
            anchors.fill: parent
            onClicked: {
                rect.signalA("gong jian bo 1992")
            }
        }

        Component.onCompleted: {
            //信号--方法
            rect.signalA.connect(methodA)
            //信号--信号
            rect.signalA.connect(rect.signalB)
            rect.signalB.connect(methodB)
            rect.signalB.connect(methodC)
        }

        //函数可以放到js文件中
        function methodA(str){
            console.log("method a",str)
        }
        function methodB(str){
            console.log("method b",str)
        }
        function methodC(){
            console.log("method c")
        }
    }
}

通过示例可以发现,用connect()可以很方便的关联信号和方法/信号。

在Qt C++中,信号槽的关联需要信号和槽的参数匹配(槽的参数个数不能多于信号定义的个数),且从左至右一一对应。但是在测试过程中,我发现由于js函数参数机制不一样,导致函数参数个数可以任意,只是未匹配的参数值为undefined而已。

(完结--)

参考

文档:Qt/Qt5.9.7/Docs/Qt-5.9.7/qtqml/qtqml-syntax-signals.html

博客:https://blog.csdn.net/liang19890820/article/details/60777593

博客:https://yq.aliyun.com/articles/119790

博客:https://blog.csdn.net/x356982611/article/details/53871748

关注
打赏
1655829268
查看更多评论
立即登录/注册

微信扫码登录

0.0853s