在Qt 5中如何获取鼠标释放事件,即使在鼠标释放之前鼠标没有移动

5
在Qt 5中似乎有些变化:如果你在调用QDrag::exec()时没有移动至少一个像素,就无法获得拖放或移动事件。尝试在可拖动图标示例的dropEvent中设置断点,然后单击一艘船并释放而不移动鼠标。这将生成一个“忽略”信号,没有任何拖放信号。
(这是在带有Qt 5.1的Kubuntu 13.10上进行的。)
当教授如何启动拖动操作时,文档建议您使用manhattanDistance()来确定鼠标是否移动足够,以真正符合“用户打算开始拖动”的条件。但你不必使用它;你可以在点击本身上启动QDrag。
有人知道解决这个问题的方法吗?还是说这个选择完全消失了? :-/

我关心的原因:长期以来,我一直在尝试在GUI应用程序中对鼠标行为进行严格控制 - 包括Qt。似乎没有可靠的状态转换图可以绘制不变量。这是一个纸牌屋,你可以很容易地通过简单的测试来证明它的错误,比如:

virtual void enterEvent(QEvent * event) {
    Q_ASSERT(!_entered);
    _entered = true;
}

virtual void leaveEvent(QEvent * event) {
    Q_ASSERT(_entered);
    _entered = false;
}

这会导致各种问题,而且它的问题会因平台而异。(暂时以Kubuntu 13.10和Qt 5.1为例)如果你按下鼠标按钮并拖出小部件,当你越过边界时,你会收到一个leaveEvent...然后在释放按钮时再收到另一个leaveEvent。如果你离开窗口并在屏幕上激活另一个应用程序中的窗口,然后在小部件内单击以重新激活Qt应用程序,你将获得两个连续的enterEvents。
对于每个鼠标事件重复此模式,并尝试牢牢掌握不变量......祝你好运!将这些固定到一个“知道”其状态并且不会崩溃的防弹应用程序中(特别是在面对狂点和alt-Tabbing时),有点难以实现。
如果你的程序进行分配并且有大量处理,而且不想在地毯下面做很多清理工作(例如,“哦,我正在响应进入而进行一些处理...但我刚刚没有离开就再次进入了。嗯,我猜那会发生!把当前的计算扔掉,重新开始...”),这是不好的。
过去我处理所有鼠标操作(甚至是简单的点击)都使用拖放。让操作涉及操作系统的拖放功能似乎会产生更强壮的体验。我只能推测这是因为测试人员实际上必须考虑诸如使用alt-Tab进行任务切换等问题,而不会导致多个放置操作或仅仅忘记已启动的操作。
但是,“嵌入到框架之上”的方面使得这个“一像素移动”要求不可能改变。我尝试通过设置计时器事件,然后伪造QMouseEvent来在拖动生效时将光标移动到新位置来绕过它。然而,我推测拖放是在平台级别上挂钩的,并且不会查询普通的Qt事件队列:src/plugins/platforms/xcb/qxcbdrag.cpp

由于似乎还没有人知道解决方法,因此我已经在Qt跟踪器中开了一个问题 - HostileFork says dont trust SE
我遇到了同样的问题,我通过调用系统API方法来模拟鼠标移动来解决了这个问题。当拖动开始时,我使用这种方法进行了处理。 - dvvrd
@dvvrd,我已经开了一个赏金。如果你能分享你的代码,那听起来就是一个很好的获得它的候选人...! - HostileFork says dont trust SE
看起来你的 bug 终于被注意到了,很快就会被修复。所以现在我必须问一下,你真的需要那段代码吗?此外,我的解决方法非常肮脏且丑陋,我有点不好意思把它放在这里 :) 思路只是模拟一些鼠标事件,在拖动开始时(使用 QTest 或本地系统 API)。 - dvvrd
1个回答

0
该问题已经在2014年5月1日被Qt团队确认为一个bug:

https://bugreports.qt-project.org/browse/QTBUG-34331

看起来我在这里提出了悬赏,最终引起了他们的注意,尽管它没有产生任何我可以接受以解决问题的SO答案。所以我写了自己的答案并接受了它。干得好,我自己。很抱歉没有更好的答案。 :-/

Qt5变化的另一个不幸的副作用是由“Dmitry Mordvinov”指出的:

我也有同样的问题。此外,在拖动开始之前,应用程序事件不会被处理,这真的是一个非常讨厌的错误。例如,在那一刻所有应用程序动画都会暂停,或者当您尝试使用触摸监视器拖动时,应用程序会挂起。

@dvvrd不得不解决这个问题,但他觉得解决方法太丑陋了,不想分享。因此,如果您受到该问题的影响,则正确的做法是参与讨论...并在问题跟踪器中发表您的声音,以提高解决方案的优先级。

(或者更好的方法:修补它并提交补丁。毕竟,这是开源的...)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接