QML - 捕获子对象的所有 UI 事件
Posted
技术标签:
【中文标题】QML - 捕获子对象的所有 UI 事件【英文标题】:QML - Capture all UI events of children objects 【发布时间】:2017-05-15 21:56:37 【问题描述】:在我的 QML 项目中,我需要一个对象来捕获其子对象的所有 UI 事件。因此,如果它的任何子对象注册了单击或其他内容,则父对象需要知道它。这里的问题是所有子对象都是预定义的类,例如 MyButton 或 MyComboBox。这些类都定义了不能被覆盖的 MouseAreas 和 onClicked() 函数。因此,我需要父对象在不修改子对象的 MouseAreas 的情况下捕获其子对象的所有事件。请告诉我完成此任务的最佳方法。
【问题讨论】:
你需要知道哪个MouseArea
被点击了吗?
【参考方案1】:
您可以爬取对象树,将一个函数连接到每个onClicked
-信号。
为此,我们需要三个部分:
应连接的信号 进行爬取的函数 创建另一个函数以使用自定义参数调用信号的函数。我选择了,我的信号必须有参数:sender
和 arguments
。 Sender 是我点击的对象,arguments
是被点击对象的clicked
信号的参数。这对于 QtQuick.Controls 2.x Button
s 是空的,并且包含一个用于 MouseArea
s 的条目 (mouse
)。
signal somethingWasClicked(var sender, var arguments)
由于对于每个可点击对象,此信号与clicked
的签名不同,因此我们无法将其直接连接到此信号。我们需要一个为我们调用信号的中间函数,在它的范围内有所需的参数并且没有参数。我们需要为我们监视的每个对象动态构建它。
function createSpyFunction(object)
return function() somethingWasClicked(object, arguments)
最后是爬虫功能。我们需要将我们创建的函数存储在某个地方。为此,我利用了所有 QtObject
s 在某种意义上都是 JS 对象的事实,因此我可以对它们使用 Object.defineProperty
to dynamically add 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])
这个函数我终于调用了
Component.onCompleted: crawlObj(this.contentItem)
我的程序的根ApplicationWindow
。
因为我只在Component.onCompleted
-handler 中调用它,在此之后添加的对象不会被监视。为了改变这一点,我们还需要监视onChildrenChanged
,并抓取新添加的对象。那里的过程几乎相似,所以这留给用户作为练习,或者可能会受到新问题的影响。
【讨论】:
是的,它做到了。谢谢!【参考方案2】:您可以尝试使用MouseArea
覆盖您的项目。在事件处理程序中,您可以检查位置并调用底层项目的事件处理程序。
Item
MyButton id: mybutton
/* set the anchors */
MyMouseComboBox id: myMouseComboBox
/* set the anchors */
MouseArea
anchros.fill: parent
onClicked:
// mouse.accepted = false
// Check whether clicked point is within mybutton
// on true, call mybutton.doSomething()
// or call mybotton.onPressed(mouse)
【讨论】:
那么你不能在任何其他MouseArea
s 中处理onPressed
-handler
没有。可以通过调用mybutton.onPressed(mouse)
来调用处理程序
是的,所以你需要通过对象树找到所有MouseArea
s,其中它们的层是未知的。
OP 写了关于自定义组件的使用。所以我假设他知道哪些组件正在使用以及位置在哪里。否则需要另一种解决方案。
如果是这样,他可以直接处理事件以上是关于QML - 捕获子对象的所有 UI 事件的主要内容,如果未能解决你的问题,请参考以下文章