我刚刚使用SDL编写了一些简单的程序,这让我回想起我编写的一些Java GUI。
在简单的SDL程序中,我有一个循环来检查任何事件(按键,鼠标点击等......)并对它们做出反应。基本上它是对投入的轮询。
在Java中,您将侦听器附加到GUI对象,并在发生某些事件时触发侦听器。
我的问题是,Java是否只是在后台为我们处理这个轮询循环,并解决了点击哪个GUI控件以便它可以触发正确的监听器,或者是否有更复杂的事情发生?
我知道Qt有一个与Java类似的事件系统,您可以使用插槽将处理程序连接到GUI控件。这也只是处理所有轮询并确定为我们点击了哪个控件?或者,是否有更复杂的事情发生?
更新
也许我对这个问题不够清楚。我真的想知道一个事件如何桥接OS层 - 应用层边界。应用程序是否轮询操作系统层并将事件信息提取到应用程序中?或者操作系统是否有某种方法可以中断/通知应用程序发生了事件,并将事件信息推送到应用程序。
我建议第三个解决方案是应用程序调用阻塞本机函数,如:
Event e = someNativeFunction(); // blocks until someNativeFunction() returns an event
答案 0 :(得分:5)
“...... Java是否只为我们在后台处理这个轮询循环......?”
差不多,是的。 UI系统为程序提供对包含已发生事件和目标的队列的访问。该程序通过循环请求来自此队列的项目,然后执行任何操作。像Qt和Java这样的库调用窗口小部件类中的特殊函数,告诉它们事件已经发生,以便系统可以从那里运行,但是由API规定。该库必须从系统特定的窗口ID转换为管理该窗口小部件的类,以便这样做。
Qt以受保护的虚拟onXxxxEvent()
函数的形式提供对此功能的访问。许多小部件的标准行为是响应事件生成信号,但这些始终是特定小部件特定事件的一些翻译形式。 Qt为您提供访问权限,以便您可以覆盖窗口小部件处理事件的方式,或者为之前从未侦听过的事件添加其他行为(通过子类化)。
每个UI系统略有不同,但根据我的经验,它们在这方面基本相同。我们在这里谈论原始的win32和Xlib。
答案 1 :(得分:4)
正如之前的回答者所说,它是系统特定的,可以以任何一种方式实施。
如果我记得Windows API(很久以前),那么每个事件都会调用一个“Window函数”,我根据事件类型做了一个大转换来选择正确的动作。
我认为大多数工具包都会抽象出来,就像带有事件调度队列的Java AWT一样。
对于X协议,输入事件(以及“您的窗口需要绘制”)通过线路作为事件消息,并由工具包库来转换或者在应用程序函数调用中,或者将它们添加到稍后要查询的队列中。
事实上,X协议(基本上)有两个字节流:一个从应用程序(“客户端”)到系统(“服务器”),另一个在另一个方向。客户端发送请求包,服务器发回结果(对于某些类型的请求),错误(如果由于某种原因无法满足某些请求)和事件(当显示器上发生某些事情时,如鼠标移动,按键,窗口调整大小,......)。对于现代系统上的本地显示器,这通常由一些共享内存机制实现,但原则上这可以通过TCP(或者今天主要通过SSH)进行远程连接(因此“通过线路”)。
我曾经开始创建一个纯Java X客户端实现(没有完成,因为我发现了其他更有趣的事情),在那里我只使用一个Socket,其InputStream和OutputStream连接到服务器。因此,原则上我使用Socket-InputStream的阻塞本机read()
函数来等待事件(以及结果和错误)。我也可以在非阻塞模式下使用java.nio.SocketChannel,然后基本上我会有一个轮询循环(当然在其他事情之间做)。 (或者我可以使用选择器,等到新的可读数据存在 - 因此也会阻塞。)
我不知道Java和Linux的Solaris实现使用的AWT-for-X实现使用了什么机制 - 我想它们基于一些本机工具包,而后者又基于X客户端库(用于C)“Xlib”,但我不知道在基地是否有投票,阻止等待或被某人调用。
答案 2 :(得分:2)
我不熟悉Qt,但基本上是Java,是的。在实践中它变得更加复杂,有模态对话框等,但基本上它是从底层操作系统(键盘和鼠标)获取事件并将它们作为事件发布在EventQueue上,各种组件获取这些事件并使用和消费它们或按照自己的意愿传递它们。
侦听器框架允许组件确定事件的内容,并将适当的信息传递给适当的侦听器。
答案 3 :(得分:1)
这是最古老的资源,但顺便说一下Java AWT/Swing event queue