【问题标题】:Events and event handling under the hood引擎盖下的事件和事件处理
【发布时间】:2011-06-29 23:41:34
【问题描述】:

我刚刚完成了一些使用 SDL 的简单程序,这让我想起了我编写的一些 Java GUI。

在简单的 SDL 程序中,我有一个循环来检查任何事件(按键、鼠标点击等)并对其做出反应。本质上是轮询输入。

在 Java 中,您将侦听器附加到 GUI 对象,并且当某些事件发生时会触发侦听器。

我的问题是,Java 是否只是在后台为我们处理这个轮询循环并计算出单击了哪个 GUI 控件以便触发正确的侦听器之类的事情,还是发生了更复杂的事情?

我知道 Qt 具有与 Java 类似的事件系统,您可以使用插槽将处理程序连接到 GUI 控件。这是否也只是处理所有轮询并确定为我们单击了哪个控件?或者,是否发生了更复杂的事情?

更新

也许我对这个问题不够清楚。我真的很想找出事件如何桥接操作系统层 - 应用程序层边界。应用程序是否轮询操作系统层并将事件信息拉入应用程序?或者操作系统是否有某种方式来中断/通知应用程序发生了事件并将事件信息推送到应用程序。

有人向我建议了第三种解决方案,即应用程序调用阻塞本机函数,例如:

Event e = someNativeFunction(); // blocks until someNativeFunction() returns an event

【问题讨论】:

    标签: java c++ events event-handling


    【解决方案1】:

    "...Java 是否只是在后台为我们处理这个轮询循环...?"

    差不多,是的。 UI 系统为程序提供对包含已发生事件和目标的队列的访问权限。程序运行一个循环,从这个队列中请求项目,然后做任何事情。 Qt 和 Java 等库调用小部件类中的特殊函数,告诉它们发生了事件,以便系统可以从那里运行,但由 API 规定。库必须将系统特定的窗口 ID 转换为管理该小部件的类才能执行此操作。

    Qt 以受保护的虚拟onXxxxEvent() 函数的形式提供对该函数的访问。许多小部件的标准行为是生成信号以响应事件,但这些总是特定于特定小部件的事件的某种翻译形式。 Qt 为您提供了对此的访问权限,以便您可以覆盖小部件处理事件的方式或为它以前从未监听过的事件添加额外的行为(通过子类化)。

    每个 UI 系统都略有不同,但根据我的经验,它们基本上都是相同的。我们在这里讨论的是原始的 win32 和 Xlib。

    【讨论】:

    • 我将更新我的问题以使其更清楚,但我真正感兴趣的是事件如何进入该队列(如果队列在应用程序中)。如果队列位于操作系统层,那么显然轮询是有意义的。
    • 实际上您可以将其视为操作系统层。这是系统特定的。
    【解决方案2】:

    正如回答者之前所说,它是特定于系统的,可以通过任何一种方式实现。

    如果我记得 Windows API 没错(很久以前),有一个“窗口函数”会为每个事件调用,我做了一个很大的改变来根据事件类型选择正确的操作。

    我认为大多数工具包都将其抽象出来,例如带有事件调度队列的 Java AWT。

    对于 X 协议,输入事件(以及“您的窗口需要被绘制”)作为事件消息通过网络传输,这取决于工具包库来转换它要么在应用程序函数调用中,要么将它们添加到稍后查询的队列中。

    X 协议实际上(基本上)与两个字节流一起工作:一个从应用程序(“客户端”)到系统(“服务器”),一个在另一个方向。客户端发送请求包,服务器返回结果(对于某些类型的请求)、错误(如果某些请求由于某种原因无法满足)和事件(当显示器上发生某些事情时,例如鼠标移动、按键, 窗口调整大小, ...)。

    对于现代系统上的本地显示,这通常由一些共享内存机制实现,但原则上这可以通过 TCP(或今天主要通过 SSH)进行远程连接(因此是“通过网络”)。

    我曾经开始创建一个纯 Java X 客户端实现(没有完成,因为我发现了其他更有趣的事情要做),然后我只是使用带有 InputStream 和 OutputStream 的 Socket 连接到服务器。因此,原则上我使用了 Socket-InputStream 的 blocking 本机 read() 函数来等待事件(以及结果和错误)。我也可以在非阻塞模式下使用 java.nio.SocketChannel,然后基本上我会有一个 轮询循环(当然,在两者之间做其他事情)。 (或者我可以使用选择器,等到有新的可读数据出现——因此也会阻塞。)

    我不知道 Linux 使用的 AWT-for-X 实现和 Java 的 Solaris 实现使用的是什么机制 - 我想它们基于一些本机工具包,而后者又基于 X 客户端库(用于C) "Xlib",但不知道在 base 中是否有轮询、阻塞等待或被某人调用

    【讨论】:

    • 再说一次,这不是我真正要问的。你说“通过网络发送事件消息”。解释一下。这就是我要找的。是否有一些系统轮询这些消息的“线路”和一些阻塞,等待这些消息作为本机函数的返回值传递?即使是一个特定系统如何工作的例子也会很有趣。
    • 对不起,我好像没听懂你的问题……(我会在我的回答中添加你添加的问题的答案)。
    【解决方案3】:

    我不熟悉 Qt,但基本上在 Java 中,是的。在实践中,它变得更加复杂,使用模式对话框等,但基本上它是从底层操作系统(用于键盘和鼠标)获取事件并将它们作为事件发布到 EventQueue 上,各种组件获取这些事件并使用和随心所欲地消费或传递。

    侦听器框架允许组件确定事件是关于什么的,并将有关它的适当信息传递给适当的侦听器。

    【讨论】:

    • 所以我的问题不是 Java 知道事件后如何处理事件,而是它们如何从操作系统层到达您的应用程序层。即,应用程序如何发现事件已发生?
    【解决方案4】:

    这是最旧的资源,但是顺便提一下Java AWT/Swing event queue

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-11
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 2010-09-12
      相关资源
      最近更新 更多