QT - 信号和事件处理系统

QT - 信号和事件处理系统

应用程序和用户界面组件需要相互通信。例如,一个按钮需要知道用户已单击它。该按钮可以更改颜色以指示其状态或执行某些逻辑。同样,应用程序需要知道用户是否正在单击按钮。应用程序可能需要将此点击事件中继到其他应用程序。

QML具有信号和信号处理机制,其中信号是事件,信号通过信号处理程序进行响应。发出信号时,将调用相应的信号处理程序。在处理程序中放置诸如脚本或其他操作之类的逻辑,使组件可以响应事件。

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

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

例如,来自Qt Quick Controls模块的Button类型具有一个信号,该信号在单击按钮时发出。在这种情况下,用于接收此信号的信号处理程序应为onClicked。在下面的示例中,每当单击按钮时,都会调用处理程序,并为父Rectangle应用随机颜色:

  import  QtQuick  2.14
  import  QtQuick.Controls  2.14
  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);
          }
      }
  }

属性更改信号处理程序

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

例如,鼠标区域类型具有按下Pressed特性。要在此属性更改时接收通知,请编写名为onPressedChanged的信号处理程序:

    import  QtQuick  2.14

    Rectangle  {
      id:  rect  width:  100;  height:  100
      TapHandler  {
          onPressedChanged:  console.log("taphandler pressed?",  pressed)
      }
  }

尽管TapHandler文档中没有记录名为的信号处理程序onPressedChanged,该信号还是由该pressed属性存在的事实隐式提供的。

使用连接(Connections)类型

在某些情况下,可能希望访问发出该信号的对象之外的信号。为此,QtQuick模块提供用于连接任意对象信号的Connections类型。该连接对象可以接收来自它的指定的任何信号的目标

例如,onClicked在前面的示例中的处理程序可能已被由所述根接收矩形代替,通过将onClicked处理程序在一个连接具有其对象目标集到button

    import  QtQuick  2.14
    import  QtQuick.Controls  2.14
    Rectangle  {  id:  rect  width:  250;  height:  250

    Button  {
      id:  button
      anchors.bottom:  parent.bottom
      anchors.horizontalCenter:  parent.horizontalCenter
      text:  "Change color!"
  }

  Connections  {
      target:  button
      onClicked:  {
          rect.color  =  Qt.rgba(Math.random(),  Math.random(),  Math.random(),  1);
      }
    }
  }

附加信号处理程序

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

例如,Component.onCompleted是一个附加的信号处理程序。创建过程完成后,通常用于执行一些JavaScript代码。示例如下:

  import  QtQuick  2.14

  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处理程序没有响应于completed从信号矩形类型。而是,带有信号的Component 附加类型的对象已由QML引擎completed自动附加Rectangle对象。创建Rectangle对象时,引擎会发出此信号,从而触发Component.onCompleted信号处理程序。

附加的信号处理程序允许将对每个单独对象重要的特定信号通知给对象。Component.onCompleted例如,如果没有附加的信号处理程序,则一个对象如果不从某个特殊对象注册某些特殊信号就无法接收该通知。所述附接的信号处理程序机制使得对象以接收特定的信号而无需额外的代码。

有关附加信号处理程序的更多信息,请参见附加属性和附加信号处理程序。

向自定义QML类型添加信号

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

定义新信号的语法为:

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

通过调用信号作为一种方法来发出信号。

例如,以下代码在名为的文件中定义SquareButton.qml。根矩形对象具有一个activated信号,每当子被发射TapHandlertapped。在此特定示例中,激活的信号以鼠标单击的x和y坐标发出:

  // SquareButton.qml
  import  QtQuick  2.14
  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(mouseXY.x,  mouseXY.y)
          onPressedChanged:  mouseXY  =  handler.point.position
      }
  }

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

// myapplication.qml
SquareButton {
    onActivated: console.log("Activated at " + xPosition + "," + yPosition)
}

有关为自定义QML类型编写信号的更多详细信息,请参见信号属性

将信号连接到方法和信号

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

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

  import  QtQuick  2.14
  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方法可以通过多种方法接收信号,如前所述,这对于信号处理程序来说是不可能的,因为它们必须唯一地命名。同样,该connect方法在将信号连接到动态创建的对象时很有用。

disconnect()消除连接信号的相应方法:

  Rectangle  {
      id:  relay
      //...
      function  removeTelegraphSignal()  {
          relay.messageReceived.disconnect(sendToTelegraph)
      }
  }

信号对信号连接

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

  import  QtQuick  2.14

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

每当发射TapHandlertapped信号时,该send信号也会自动发射。

output:
    MouseArea clicked
    Send clicked
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容

  • QML对象属性 每个QML对象类型都有一组定义的属性。使用为该对象类型定义的属性集创建对象类型的每个实例。可以指定...
    YottaYuan阅读 2,037评论 0 4
  • 引自:https://blog.51cto.com/9291927/2070398 Qt高级——Qt信号槽机制源码...
    Magic11阅读 3,955评论 1 12
  • 13.动态 QML(Dynamic QML) 本章的作者:e8johan ** 注意: **最新的构建时间:201...
    赵者也阅读 2,709评论 0 5
  • 《Qt 学习之路 2》原文地址 Qt跨平台策略 GUI 模拟:任何平台都提供了图形绘制函数,例如画点、画线、画面等...
    CharlesZhangCh阅读 2,013评论 0 5
  • 当高铁穿过时间的隧道, 依然回不去曾经的年少! 读书,细语,追逐, 还有泡面的味道。 一天两夜,谁的肩膀可以依靠?...
    以海为船阅读 139评论 0 4