【发布时间】:2017-05-16 03:24:49
【问题描述】:
我正在开发一个自定义跨平台 UI 库,该库需要一个同步的“ShowPopup”方法来显示一个弹出窗口,运行一个事件循环直到它完成,并在点击弹出窗口外部或按 Esc 键时自动取消。键盘、鼠标和滚轮事件需要分派到弹出窗口,但其他事件(绘画、绘图、计时器等)需要在循环运行时分派到它们的常规目标。
编辑:为了澄清起见,弹出窗口是指这种菜单样式的弹出窗口,而不是警报/对话框等...
在 Windows 上,我通过调用 GetMessage/DispatchMessage 并根据需要过滤和分派消息来实现这一点。工作正常。
但是,我对 Cocoa/OS X 的经验要少得多,并且发现整个事件循环/调度范例有点令人困惑。我看过以下文章,它解释了如何实现与我需要的非常相似的鼠标跟踪循环:
但是...这有一些让我担心的事情。
链接的文章指出:“应用程序的主线程在事件跟踪循环期间无法处理任何其他请求,并且计时器可能不会触发”。可能不?为什么不,如果不,如何确保他们这样做?
nextEventMatchingMask:untilDate:inMode:dequeue: 的文档指出“与指定事件类型之一不匹配的事件将留在队列中。”。这似乎有点奇怪。这是否意味着如果事件循环只要求鼠标事件,那么一旦循环完成,任何按下的键都会被处理?那会很奇怪。
-
是否可以在不删除事件队列的情况下查看消息。例如:我的库的 Windows 版本在外部单击时使用它来关闭弹出窗口,但将单击事件留在队列中,以便在另一个按钮上单击弹出窗口外部不需要第二次单击。
我已经阅读并重新阅读了有关运行循环模式的内容,但仍然没有真正理解。很好地解释这些是什么。
还有其他实现弹出事件循环的好例子吗?更好的做法是使用内置 NSApplication 运行循环的伪代码。
另一种表述方式... Cocoa 相当于 Windows 的 PeekMessage(..., PM_REMOVE)、PeekMessage(..., PM_NOREMOVE) 和 DispatchMessage()。
非常感谢任何帮助。
【问题讨论】:
-
与用户交互或旋转事件循环的同步方法是虚构的。他们公然对用户撒谎,然后出现错误,因为从未打算重新输入的代码是。我强烈建议根本没有任何同步事件循环旋转方法。没有任何。在这个世纪和十年里,没有人应该再这样编程了。
-
当 UI 元素改变状态 - 即弹出窗口被关闭时,会从事件循环/调度程序内向相关方发出异步通知。如果应用程序不是微不足道的,您将希望在由这些事件驱动的(例如 UML/SCXML)状态机中正式描述其行为,否则您可以直接使用它们。重新进入事件循环是不可移植的——即在不同的平台上,不同的可重入事件将从子循环发出,并且它颁布了直接导致意大利面条代码的虚构。 UI 不同步。从来没有。
-
@KubaOber 谢谢 - 上传图片。至于旋转同步事件循环——这正是 Apple 文档所描述的,所以我不认为它是“虚构的”。此外,我最终使用 Ken Thomases 回答的提示使其完美运行。