QML - 捕获子对象的所有 UI 事件

use*_*354 2 events qt listener qml

在我的 QML 项目中,我需要一个对象来捕获其子对象的所有 UI 事件。所以,如果它的任何一个子对象注册了一个点击或其他东西,父对象需要知道它。这里的问题是所有子对象都是预定义的类,例如 MyButton 或 MyComboBox。这些类都定义了不能被覆盖的 MouseAreas 和 onClicked() 函数。因此,我需要父对象在不修改子对象的 MouseAreas 的情况下捕获其子对象的所有事件。请让我知道实现此目的的最佳方法。

der*_*erM 5

您可以爬行对象树,将函数连接到每个onClicked信号。

为此,我们需要三个部分:

  • 应连接的信号
  • 进行爬行的函数
  • 创建另一个函数以使用自定义参数调用信号的函数。

我选择了,我的信号必须有参数:senderarguments。Sender 是我点击的对象,是点击对象argumentsclicked-signal的参数。这对于QtQuick.Controls 2.x Buttons是空的,并且包含一个条目 ( mouse) 用于MouseAreas。

signal somethingWasClicked(var sender, var arguments)
Run Code Online (Sandbox Code Playgroud)

由于此信号与clicked每个可点击对象的签名不同,因此我们无法将其直接连接到此信号。我们需要一个为我们调用信号的中间函数,在它的作用域中有所需的参数并且没有参数。我们需要为我们监视的每个对象动态构建它。

function createSpyFunction(object) {
    return function() { somethingWasClicked(object, arguments) }
}
Run Code Online (Sandbox Code Playgroud)

最后是爬网功能。我们需要将我们创建的函数存储在某个地方。为此,我利用了QtObject在某种意义上所有s 都是 JS-Objects的事实,因此我可以使用Object.defineProperty 动态向它们添加 JS-properties。在这里我可以存储我们的函数,而不需要自己修改组件的源代码。创建这个函数后,我connect把它交给onClicked-handler。

function crawlChildren(obj) {
    if (obj.onClicked) {
        Object.defineProperty(obj, '__clickedFunction', { value: createSpyFunction(obj) })
        obj.onClicked.connect(obj.__clickedFunction)
    }
    if (obj.children) {
        var i = 0
        for (; i < obj.children.length; i++) {
            crawlChildren(obj.children[i])
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我终于调用了这个函数

Component.onCompleted: crawlObj(this.contentItem)
Run Code Online (Sandbox Code Playgroud)

ApplicationWindow我的程序的根。


因为我只在Component.onCompleted-handler 中调用它,在此之后添加的对象不会被监视。要改变这一点,我们还需要监视onChildrenChanged和抓取新添加的对象。那里的过程几乎相似,因此这留给用户作为练习,或者可能会受到新问题的影响。