在运行Swing程序的过程中
首先生成UI线程(事件调度线程,EDT)?
大概任何给定的JVM都可以做任何想要的事
(例如,始终在启动时生成EDT,无论是否
是否曾经使用过),但实际上
EDT通常是创建的吗?
它是否在SwingUtilities.invokeLater()时创建
首先叫?何时首次实例化JPanel?
并且如果事件泵是与创建分开启动的
EDT,通常什么时候发生?
最佳答案
浏览完代码后,似乎它是“延迟初始化的”,这意味着它可以在需要时立即初始化(如果尚未初始化)。在这种情况下,无论何时将任何事件发布到它的队列中。
这是完整的故事:EventDispatchThread
封装在EventQueue
中。每个EventQueue
都有自己的EDT:
/**
* Just a summary of the class
*/
public class EventQueue {
private static final int ULTIMATE_PRIORITY = 3;
private static final int NUM_PRIORITIES = ULTIMATE_PRIORITY + 1;
private Queue[] queues = new Queue[NUM_PRIORITIES];
private EventQueue nextQueue;
private EventQueue previousQueue;
private EventDispatchThread dispatchThread;
}
使用package-private方法
dispatchThread
初始化initDispatchThread()
:final void initDispatchThread() {
pushPopLock.lock();
try {
if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) {
dispatchThread = AccessController.doPrivileged(
new PrivilegedAction<EventDispatchThread>() {
public EventDispatchThread run() {
EventDispatchThread t =
new EventDispatchThread(threadGroup,
name,
EventQueue.this);
t.setContextClassLoader(classLoader);
t.setPriority(Thread.NORM_PRIORITY + 1);
t.setDaemon(false);
AWTAutoShutdown.getInstance().notifyThreadBusy(t);
return t;
}
}
);
dispatchThread.start();
}
} finally {
pushPopLock.unlock();
}
}
在检查对此方法的引用之后,在3个地方调用了此方法:
EventQueue#wakeup(boolean)
EventQueue#postEventPrivate(AWTEvent)
(由公共方法 EventQueue#postEvent(AWTEvent)
调用)中EventQueue#createSecondaryLoop(Conditional, EventFilter, long)
中。 在调用
initDispatchThread()
之前,请检查dispatchThread
以确保尚未初始化。您可以通过几种方式在JDK中查看类的完整源代码(最容易附加源代码)。如果您真的有兴趣,请研究这些方法。因此,现在我们知道
EventQueue
包含线程,并且该线程在实际需要时就创建(事件被发布)。现在该讨论一下此队列的位置以及事物如何与之通信。如果检查
EventQueue#invokeLater(Runnable)
(由SwingUtilities
对应项调用)的代码,您会看到它调用Toolkit.getEventQueue().postEvent(...)
。这告诉我们队列位于Toolkit
中。在
Toolkit
类内部,我们可以随时查看它是否已创建(如果尚未创建)。它使用反射来创建对象:public static synchronized Toolkit getDefaultToolkit() {
if (toolkit == null) {
try {
java.lang.Compiler.disable();
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
String nm = null;
Class<?> cls = null;
try {
nm = System.getProperty("awt.toolkit");
try {
cls = Class.forName(nm);
} catch (ClassNotFoundException e) {
ClassLoader cl = ClassLoader.getSystemClassLoader();
if (cl != null) {
try {
cls = cl.loadClass(nm);
} catch (ClassNotFoundException ee) {
throw new AWTError("Toolkit not found: " + nm);
}
}
}
if (cls != null) {
toolkit = (Toolkit)cls.newInstance();
if (GraphicsEnvironment.isHeadless()) {
toolkit = new HeadlessToolkit(toolkit);
}
}
} catch (InstantiationException e) {
throw new AWTError("Could not instantiate Toolkit: " + nm);
} catch (IllegalAccessException e) {
throw new AWTError("Could not access Toolkit: " + nm);
}
return null;
}
});
loadAssistiveTechnologies();
} finally {
// Make sure to always re-enable the JIT.
java.lang.Compiler.enable();
}
}
return toolkit;
}
工具箱是一个抽象类。我们没有实例化此类的对象,而是创建Toolkit子类的一个实例:
SunToolkit
。我们将需要知道这一点,以查看在何处创建队列。一旦有了工具包,我们就可以使用
Toolkit#getSystemEventQueue()
访问它的EventQueue。这将望远镜观察到受保护的抽象方法getSystemEventQueueImpl()
。我们必须检出子类才能看到此方法的实现。在SunToolkit类中,我们有:protected EventQueue getSystemEventQueueImpl() {
return getSystemEventQueueImplPP();
}
// Package private implementation
static EventQueue getSystemEventQueueImplPP() {
return getSystemEventQueueImplPP(AppContext.getAppContext());
}
public static EventQueue getSystemEventQueueImplPP(AppContext appContext) {
EventQueue theEventQueue = (EventQueue) appContext.get(AppContext.EVENT_QUEUE_KEY);
return theEventQueue;
}
(EventQueue) appContext.get(AppContext.EVENT_QUEUE_KEY)
队列即将到达工具箱的appContext
。现在我们要做的就是找到将队列添加到应用上下文的位置:public SunToolkit() {
Runnable initEQ = new Runnable() {
public void run() {
EventQueue eventQueue;
String eqName = System.getProperty("AWT.EventQueueClass", "java.awt.EventQueue");
try {
eventQueue = (EventQueue) Class.forName(eqName).newInstance();
} catch (Exception e) {
e.printStackTrace();
System.err.println("Failed loading " + eqName + ": " + e);
eventQueue = new EventQueue();
}
AppContext appContext = AppContext.getAppContext();
appContext.put(AppContext.EVENT_QUEUE_KEY, eventQueue); //queue added here
PostEventQueue postEventQueue = new PostEventQueue(eventQueue);
appContext.put(POST_EVENT_QUEUE_KEY, postEventQueue);
}
};
initEQ.run();
}
快速概述:
Toolkit.getDefaultToolkit()
,或者每当程序的另一部分(例如将数据发布到队列中的Swing组件)调用时)如果您对此有任何疑问,请告诉我