2

我需要在没有物理键盘的平板设备上模拟控制按键。为此,我有一个屏幕浮动按钮,用户可以使用它来实现这一点。

然而问题是只能有一个MouseArea接收触摸事件。如果一个人有焦点,其余的将被忽略。这显然是有问题的,因为这使得无法按住控制按钮并按下其他一些 GUI 元素。

请注意,在文字上下文中我不需要多点触控——每个鼠标区域只需要一次触控,我只需要多个鼠标区域同时工作。这一点,再加上MultiPointTouchArea's API 是专门为实际的多点触控量身定制的,并且缺少我实际需要的属性、功能(悬停、光标)和便利性,这也是我真的不太渴望使用它的原因,即使据说向后兼容鼠标输入。

我怀疑这种限制是由于触摸被硬塞到MouseArea而不是一等公民的事实,并且底层实现是一个光标统治他们所有的交易,但仍然,也许有一些方法使多个鼠标区域同时工作?

好的,这是一个简单的例子 - 按下屏幕的左侧或右侧分别将其变为蓝色和红色,但是如果已经按下另一个,则无法按下另一个。

Window {
  id: main
  visible: true
  width: 600
  height: 300

  Row {
    Rectangle {
      width: main.width * .5
      height: main.height
      color: m1.pressed ? "blue" : "black"
      MouseArea {
        id: m1
        anchors.fill: parent
      }
    }
    Rectangle {
      width: main.width * .5
      height: main.height
      color: m2.pressed ? "red" : "black"
      MouseArea {
        id: m2
        anchors.fill: parent
      }
    }
  }
}
4

1 回答 1

3

好吧,2 年后,之前没有答案……我会讲述我的整个历史,所以没有人会尝试我们做过的同样的事情并浪费时间。转到该行下方(图像下方一点)以跳过它。

我们有同样的问题,甚至更大,因为我们用你说的那句话设计了我们所有的系统,

即使据说向后兼容鼠标输入

请记住,在我们看到我们遇到麻烦之后的时间。

在考虑了如何解决问题之后,我们首先尝试了一个递归函数来搜索所有鼠标区域,并为每个触摸点生成一个带有标志Qt.MouseEventSynthesizedByApplication活动的假鼠标事件,并且鼠标区域可能会处理该事件,并且触发相应的回调。

在这里我放了一张失败代码的图像,所以赶时间的人不要复制它......它还没有完成,我们仍然有问题弄清楚如何处理多次触摸。 失败的代码

似乎当您在鼠标区域中有不止一次触摸时,没有为该场景编码的行为,这是有道理的,因为您应该在系统中只有一个鼠标。

然后我们在网络上搜索,在 qt 论坛的 webarchive 中找到了一个 2009 年的已删除帖子,该帖子与一个有类似问题的人有关,并发布了一个奇怪的代码(在 qt5 上不起作用)来欺骗 mousearea 接受这些事件。这让我们产生了自己生成应该发生的事件的想法,并使用假鼠标事件从相应的鼠标区域调用信号。

除了无法触发的按下(MouseEvent 鼠标)信号外,这都有效。它给出了错误。

之后,我们尝试公开信号(通过在鼠标区域上的显式声明)

property var toques = []
visible: false
property var pressed
onPressed: pressed = true
onReleased: pressed = false

这让我们更接近了一步,但它需要实现每个鼠标事件,此外,所有触摸之间存在间歇性(因为我们可能会为每次触摸触发每个信号)并且行为可能是未定义的。此外,触摸中没有顺序来跟踪发生的事情,这一事​​实使我们拒绝了这个porpuse的mousearea。


然后我们所做的就是使用MutiPointTouchArea来处理事件。我们看到使用多个 MultiPointTouchArea(s) 不会产生错误,并且可以处理应用程序的多次点击(来自触摸)。

您必须做的事情是用 Multitouch 替换 MouseAreas,并自己实现您想要的所有行为,像悬停这样的概念在这种情况下没有意义,因为我们正在处理触摸。您可能会使用压力来做类似的事情。我们放置组件Rectangle来保留我们感兴趣的变量/信号,并在发生某些操作时从 MultiTouchArea 中更改。在这里,我将根据该想法实现您的简单示例:

Window {
  id: main
  visible: true
  width: 600
  height: 300

  Row {
    Rectangle {
      width: main.width * .5
      height: main.height
      property var lol: false
      color: ispressed ? "blue" : "black"
      MultiPointTouchArea {
        id: m1
        anchors.fill: parent
        onPressed: parent.ispressed= true
        onReleased: parent.ispressed= false
      }
    }
    Rectangle {
      width: main.width * .5
      height: main.height
      x:main.width * .5
      property var ispressed: false
      color: ispressed ? "red" : "black"
      MultiPointTouchArea {
        id: m2
        anchors.fill: parent
        onPressed: parent.ispressed= true
        onReleased: parent.ispressed= false
      }
    }
  }
}

如您所见,矩形(您的按钮或其他任何东西)具有重要的属性,在这种情况下被按下,并且它会根据我们定义的行为由孩子(MultipointToucArea)更改,在这种情况下在按下时激活,并且释放时释放,注意在这种情况下,只有拉动一根手指,颜色才会消失,因为触发了 onReleased。

在每种情况下,您可能必须决定哪种行为适合您的应用程序。在我们的例子中,为编程给出的信号绰绰有余:

canceled(list<TouchPoint> touchPoints)
gestureStarted(GestureEvent gesture)
pressed(list<TouchPoint> touchPoints)
released(list<TouchPoint> touchPoints)
touchUpdated(list<TouchPoint> touchPoints)
updated(list<TouchPoint> touchPoints)

此外,您可能会看到按下仅发生在被触摸的第一个区域,因此,如果您继续将手指放在其他鼠标区域上,这些将不会触发按下事件,因此使用 updated() 您可能会得到它是否应该激活事物。

这是我们得到的解决方案,并且为我们工作,我们想不出更好的方法,对于点击/按下事件,这就是诀窍。

希望能帮助到你。

于 2018-09-26T10:30:03.587 回答