首先,我不是在询问事件处理。我知道使用Observer模式实现了处理。
让我举一个小例子。假设我在JFrame上有一个Jbutton。我单击此按钮的顶部。 现在按钮如何知道我点击了它?
1)是否有任何java线程等待点击?如果是这样的代码来自哪里(等到我点击部分)?那么每个swing组件是否都在等待线程之上的事件?我认为这是一项非常昂贵的任务。
2)如果没有,这是如何工作的?
答案 0 :(得分:2)
观察者模式在整个堆栈中使用:
我们的Swing应用程序的“事件调度线程”运行以下形式的循环:
while (!shutdownRequested) {
Event e = retrieveEventFromEventQueue(); // for instance our mouse clicked event
handleEvent(e);
}
在AWT / Swing中,有单个线程执行该代码。第一个调用将阻塞,直到新事件变为可用,handleEvent()将调用此事件的侦听器。也就是说,单个线程执行所有UI更新(这就是为什么长时间运行的任务不应该在事件监听器中完成,因为这会冻结ui),并且如果用户没有与应用程序交互,它就会休眠。
答案 1 :(得分:1)
有没有等待点击的java线程?
是的,java.awt.EventDispatchThread
。这里引用了来自java教程的the event dispatch thread section:
Swing事件处理代码在称为事件的特殊线程上运行 派遣线程。大多数调用Swing方法的代码也会运行 这个帖子。这是必要的,因为大多数Swing对象方法都是 不是“线程安全”:从多个线程调用它们冒险线程 干扰或内存一致性错误。一些Swing组件 方法在API规范中标记为“线程安全”;这些可以 从任何线程安全地调用。所有其他Swing组件方法 必须从事件派发线程调用。忽略的程序 此规则可能在大多数情况下正常运行,但受制于 难以重现的不可预测的错误。
回答你的下一个问题,
如果是这样的代码来自哪里(等到我被点击 部)?
EventDispatchThread
启动永久事件泵,并在其pumpEvents(Conditional)
方法中调用run
。
public void run() {
try {
pumpEvents(new Conditional() {
public boolean evaluate() {
return true;
}
});
} finally {
getEventQueue().detachDispatchThread(this);
}
}
任何事件处理程序都可以随时选择阻止此事件泵,但应再次调用pumpEvents(Conditional)
启动新泵(而不是新的EDT)。 Conditional
评估为false
后,此辅助事件泵将自动退出,并且会调度另外的Event
。
泵事件将调用AWTEvent#getNextEvent
,它将从事件队列中检索事件。
然后每个挥杆组件都在等待顶部的事件 线程?我认为这是一项非常昂贵的任务。
再一次,java教程回答了这个
考虑在事件派发线程上运行的代码很有用 作为一系列短期任务。大多数任务都是调用 事件处理方法,例如ActionListener.actionPerformed。其他 可以使用invokeLater或应用程序代码来安排任务 invokeAndWait。事件派发线程上的任务必须快速完成; 如果他们不这样做,未处理的事件将备份并且用户界面变为 不响应。
事件在与平台无关的类java.awt.EventQueue
中排队。事件以优先级存储在队列中,为每个优先级创建一个队列。
private static final int LOW_PRIORITY = 0;
private static final int NORM_PRIORITY = 1;
private static final int HIGH_PRIORITY = 2;
private static final int ULTIMATE_PRIORITY = 3;
从Queue of开始,事件从EventQueue中拉出 最高优先级。我们在所有队列中按顺序递减。
请注意,通常调用的某些事件会被缓存以获得更好的性能,例如PaintEvent.Paint
,PaintEvent.UPDATE
,MouseEvent.MOUSE_MOVED
,MouveSevent.MOUSE_DRAGGED
。
这并不像你想象的那么贵。
答案 2 :(得分:0)
有没有等待点击的java线程?
是的,它被称为事件调度线程(EDT)。
由于Swing中的所有组件都是轻量级的,这意味着只是一个很好的动画,仅此而已,它实际上是顶级组件,例如跟踪鼠标点击的JFrame
,并将它们传递给该像素上的组件。