忽略事件分派线程如何让这个程序工作?
How does ignoring the event dispatch thread allow this program to work?
因为我试图看看我是否可以回答 this question earlier today. I realized that I don't fully understand the Event Dispatch Thread
(EDT). Googling both confirmed and helped with that and clarified why I don't. (This 可能也与理解有关。)
该代码设置了一个 GUI,随后(如前面的问题)更新了一个文本字段,直到取消设置标志。
我有几个questions/requests.
如果两个调用(对 swingInit
和 doIt
)都在 invokeLater
块之外(如图所示),请解释为什么下面的代码运行正常,因为这两个调用都会影响或查询 GUI,但都不会在 EDT 上执行(是吗?)。那不是招来失败吗?
如果对 swingInit
的调用在内部,对 doIt
的调用在 invokeLater
外部,代码也会运行。所以 swingInit
在 EDT 上执行,但是 doIt
不在 EDT 上执行应该不会有问题吗? (我很惊讶这有效。我应该吗?)
我想我明白为什么如果 doIt
在 invokeLater
里面,不管 swingInit
在哪里,它都会挂起:invokeLater
的目的只是初始化 GUI(对吗?)。
doIt
应该只在 EDT 上启动(可能来自事件发生)但肯定 而不是 在 invokeLater
块内?
(EDT 概念的历史很有趣。并非总是如此。请参阅上面的 link 以 "why I don't" 理解它。)
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());
};
}
static void doIt(){
while(flag)
tf.setText(getInfo());
};
doIt
中的繁忙循环占用了 GUI 线程(在该循环中旋转),这将导致 GUI 挂起。
您实际上并没有解释 "runs fine" 的意思,但我假设这就是您遇到的问题。
您可能想使用 Swing Timer 来做一些类似于您在循环中所做的事情。
记下你的每一个要点:
代码在主线程上启动 - EDT 是 运行 并行的。
swingInit
returns 在构建 UI 之后
控制 EDT,允许 dotIt
在主线程上并行执行其操作
与上述类似的情况,但这里您保证在 EDT 上构建 UI(根据 Oracle 的建议)。
一个长 运行ning 任务被放置到 EDT 上,阻止它显示(如果放置在 swingIt
之前)或绘画和交互(如果放置在之后)。 the purpose of invokeLater is ONLY to initialize the GUI
目的是将非线程安全的 Swing 调用置于 EDT 上。如果在主要方法中,我建议使用 SwingUtilities.invokeAndWait
如果您希望像这样更新 UI,请考虑使用 SwingTimer
。
运行 EDT 特定的、EDT 之外的非线程安全代码不保证失败,但确实邀请失败(当两个(或更多)线程尝试同时更新数据时发生冲突)。
我曾经花了几个小时追踪一个神秘的 NullPointerException
,才意识到这是一个 LookAndFeel
问题,其调用不在 EDT 上。学过的知识。
因为我试图看看我是否可以回答 this question earlier today. I realized that I don't fully understand the Event Dispatch Thread
(EDT). Googling both confirmed and helped with that and clarified why I don't. (This 可能也与理解有关。)
该代码设置了一个 GUI,随后(如前面的问题)更新了一个文本字段,直到取消设置标志。
我有几个questions/requests.
如果两个调用(对
swingInit
和doIt
)都在invokeLater
块之外(如图所示),请解释为什么下面的代码运行正常,因为这两个调用都会影响或查询 GUI,但都不会在 EDT 上执行(是吗?)。那不是招来失败吗?如果对
swingInit
的调用在内部,对doIt
的调用在invokeLater
外部,代码也会运行。所以swingInit
在 EDT 上执行,但是doIt
不在 EDT 上执行应该不会有问题吗? (我很惊讶这有效。我应该吗?)我想我明白为什么如果
doIt
在invokeLater
里面,不管swingInit
在哪里,它都会挂起:invokeLater
的目的只是初始化 GUI(对吗?)。doIt
应该只在 EDT 上启动(可能来自事件发生)但肯定 而不是 在invokeLater
块内?
(EDT 概念的历史很有趣。并非总是如此。请参阅上面的 link 以 "why I don't" 理解它。)
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());
};
}
static void doIt(){
while(flag)
tf.setText(getInfo());
};
doIt
中的繁忙循环占用了 GUI 线程(在该循环中旋转),这将导致 GUI 挂起。
您实际上并没有解释 "runs fine" 的意思,但我假设这就是您遇到的问题。
您可能想使用 Swing Timer 来做一些类似于您在循环中所做的事情。
记下你的每一个要点:
代码在主线程上启动 - EDT 是 运行 并行的。
swingInit
returns 在构建 UI 之后 控制 EDT,允许dotIt
在主线程上并行执行其操作与上述类似的情况,但这里您保证在 EDT 上构建 UI(根据 Oracle 的建议)。
一个长 运行ning 任务被放置到 EDT 上,阻止它显示(如果放置在
swingIt
之前)或绘画和交互(如果放置在之后)。the purpose of invokeLater is ONLY to initialize the GUI
目的是将非线程安全的 Swing 调用置于 EDT 上。如果在主要方法中,我建议使用SwingUtilities.invokeAndWait
如果您希望像这样更新 UI,请考虑使用
SwingTimer
。
运行 EDT 特定的、EDT 之外的非线程安全代码不保证失败,但确实邀请失败(当两个(或更多)线程尝试同时更新数据时发生冲突)。
我曾经花了几个小时追踪一个神秘的 NullPointerException
,才意识到这是一个 LookAndFeel
问题,其调用不在 EDT 上。学过的知识。