我试图看看我是否可以回答this question earlier today。我意识到我并不完全理解Event Dispatch Thread
( EDT )。 Googling确认并帮助了这一点并澄清了why I don't。 (This也可能与理解有关。)
代码设置GUI,稍后(如前面的问题中所述)更新文本字段,直到取消设置标志。
我有几个问题/要求。
如果两个调用(swingInit
和doIt
)都在invokeLater
块之外(如图所示),请解释为什么以下代码运行正常,因为这两个调用都会影响或查询GUI但是它们都没有在EDT上执行(是吗?)。这不是故障吗?
如果swingInit
的电话位于doIt
内且invokeLater
位于swingInit
之外,则代码也会运行。所以doIt
在EDT上执行,但不应该在EDT上执行doIt
是个问题吗? (我很惊讶这有效。我应该去过吗?)
我想我理解为什么invokeLater
位于swingInit
内,无论invokeLater
位于何处,它都会挂起:doIt
的目的只是初始化 GUI(对吧?)。
只应在EDT上启动invokeLater
(可能来自发生的事件),但import static java.awt.EventQueue.invokeLater;
import java.awt.event.*;
import javax.swing.*;
public class Whatever
{
static boolean flag = true;
static JTextField tf = new JTextField("Hi",20);
static JPanel p = new JPanel();
static JFrame f = new JFrame();
static JButton b = new JButton("End");
public static void main(String[] args)
{
swingInit();
invokeLater
(
new Runnable()
{
@Override
public void run()
{
// swingInit();
// doIt();
}
}
);
doIt();
}
static void swingInit()
{
b.addMouseListener
(
new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
flag = false;
JOptionPane.showMessageDialog(null,"Clicked... exiting");
System.exit(0);
}
}
);
p.add(tf);
p.add(b);
f.add(p);
f.setVisible(true);
f.pack();
f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
static String getInfo(){
return "Hello... " + Math.random();
}
static void doIt(){
while(flag)
tf.setText(getInfo());
};
}
阻止
(EDT概念的历史很有意思。并非总是如此。请参阅上面的链接"为什么我不理解它。)
<android>
<manifestAdditions><![CDATA[
<manifest android:installLocation="auto">
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application>
<!-- this meta-data tag is required for AdMob -->
<meta-data android:name="com.google.android.gms.version" android:value="4452000"/>
<!-- this activity is required for AdMob -->
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
</application>
</manifest>
]]></manifestAdditions>
</android>
答案 0 :(得分:3)
获取每个要点:
代码在主线程上启动 - EDT并行运行。
构建后面的UI后,swingInit
返回
控制EDT,允许dotIt
在主线程上并行执行
与上述类似的情况,但在此您要保证在EDT上构建UI(按照Oracle的建议)。
长时间运行的任务被放置在EDT上,阻止它显示(如果放在swingIt
之前)或绘画和交互(如果放在后面)。 the purpose of invokeLater is ONLY to initialize the GUI
目的是将非线程安全的Swing调用放到EDT上。如果在主要方法中,我建议使用SwingUtilities.invokeAndWait
如果您希望像这样更新用户界面,请考虑使用SwingTimer
进行更新。
在EDT 之外运行EDT特定的非线程安全代码并不能保证失败,但它会邀请失败(当两个(或更多)线程发生冲突时)尝试同时更新数据)。
我曾经花了几个小时追踪一个神秘的NullPointerException
,但却意识到这是一个LookAndFeel
问题,其电话不在美国东部时间。学过的知识。
答案 1 :(得分:2)
static void doIt(){
while(flag)
tf.setText(getInfo());
};
doIt
内的忙循环占用GUI线程(在该循环中旋转),这将导致GUI挂起。
你没有真正解释你的意思&#34;运行得很好&#34;但是我认为这是你所看到的问题。
您可能希望使用Swing Timer来执行类似循环中所做的操作。