我有以下fun将由非事件派发线程执行.在线程中间,我想要一个
但是,我发现以线程安全方式执行它并不容易,因为对话框应该由事件调度线程显示.我试试
public int fun()
{
// The following code will be executed by non event dispatching thread.
final int choice;
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
// Error.
choice = JOptionPane.showConfirmDialog(SaveToCloudJDialog.this, message, title, JOptionPane.YES_NO_OPTION);
}
});
return choice;
}
Run Code Online (Sandbox Code Playgroud)
当然这不会choice是最终的,我不能将对话框的返回值分配给它.
实现上述3个目标的正确方法是什么?
有人可以向我解释为什么我放弃了选择(设置setSelected())JCheckBox时我放入JOptionPane了ItemListener?这是一个错误吗?
很奇怪,如果这个过程延迟invokeLater(),setSelected()正如我预期的那样正常工作.

来自SSCCE
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ComponentEventDemo extends JPanel
implements ComponentListener, ItemListener {
private static final long serialVersionUID = 1L;
private JFrame frame;
private JTextArea display;
private String newline = "\n";
private JTextField field1;
public ComponentEventDemo() {
super(new BorderLayout());
display = new JTextArea(10, 25);
display.setEditable(false);
JPanel panel = new JPanel(new GridLayout(0, 2));
field1 = new JTextField();
field1.setDisabledTextColor(Color.red);
JCheckBox checkbox = new JCheckBox("Label visible", …Run Code Online (Sandbox Code Playgroud) 我已经找到了许多关于正确使用EDT的教程和示例,但是我想听听应该如何反过来:检查一个复杂的应用程序,它具有Swing GUI和许多涉及长网络操作的功能,并找到EDT所在的位置使用不当.
我发现了
SwingUtilities.isEventDispatchThread()
Run Code Online (Sandbox Code Playgroud)
可以用来检查一段代码是否在EDT中,所以我可以检查所有长操作都不会发生在SwingUtilities.isEventDispatchThread()返回true的地方.
这样对吗?是否有更好的方法可以调试整个应用程序以寻找错误使用EDT?谢谢.
java user-interface swing thread-safety event-dispatch-thread
另请参阅Java Swing GUI沙漏.但是,提供的答案似乎不起作用.
我有以下代码:
private void loadFileMenuItemActionPerformed(java.awt.event.ActionEvent evt) {
int returnVal = fileChoser.showOpenDialog(this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
try {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// do stuff
} finally {
this.setCursor(Cursor.getDefaultCursor());
}
}
}
Run Code Online (Sandbox Code Playgroud)
当用户在菜单栏中选择相应条目时调用此方法.但是光标永远不会改变.请注意,加载文件需要一个文件,因此应该可以看到光标的变化.
我究竟做错了什么?
编辑:
this 是顶级JFrame.
编辑2:将解决方案移至单独的答案
Java能够一次创建多个EDT吗?
我正在尝试设置EDT以及如何更新"重型"面板的内容,其中可能有十几个面板嵌入其中并且共有数百个组件.目前我有
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
panel.update();
}
});
}
Run Code Online (Sandbox Code Playgroud)
我查看了以下帖子:
http://en.wiki2.org/wiki/Event_dispatching_thread
等等.
我有点明白,如果有一个EDT必须处理的十几个事件,Java已经有了一个内部调度机制来对这些事件进行分组/优先级排序.
根据http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html
"This is necessary because most Swing object methods are not "thread safe": invoking them from multiple threads risks thread interference or memory consistency errors."
Run Code Online (Sandbox Code Playgroud)
那么如果我用新线程创建第二个EDT(下面的新Runnable(){...} .start()怎么办?
为了避免线程安全,java会自动将两个EDT合并为一个吗?
new Thread(new Runnable() {
public void run() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
panel.update();
}
});
}
}).start();
Run Code Online (Sandbox Code Playgroud) 我有一个用Swing实现的UI.一个组件做了一些可能需要一些时间的工作,所以我使用了SwingUtilities.invokeLater.但是,我正在阅读一些旧代码并在以下内容中找到ActionListener:
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// code X
}
});
} else {
// code X
}
Run Code Online (Sandbox Code Playgroud)
我认为它有意义,因为它与code XEDT 分开.但是,我发现它很容易出错,因为我已经使用了几次,而且两次都忘记了这else部分.
问题是:SwingUtilities.isEventDispatchThread()检查是否必要?或者我可以假设我不在EDT并且总是使用invokeLater?
非常感谢.
我们遇到了一个错误,我们无法追踪到什么东西冻结了我们的摇摆线程(它已经差不多2周了,没有真正的结果) - 我们是经验丰富的Swing程序员,但我们有一个庞大的程序,并相信它是在一些遗留代码
我想知道,除了编辑EventQueueJDK中的实际类之外还有什么方法可以让我们查看当前在事件调度线程上运行的所有代码 - 也许某种类型的工具可以让我们查看它们的内容进入或离开事件派遣线程?
我知道这个问题已经在许多问题上被看到并且已经得到了回答,但是,我仍然无法理解它.
我只想在提取大型xml文件的某些内容时更新progressBar.我认为在不同的线程中使用耗时的循环已经足够了但是?所有我设法获得的是progressBar要么根本没有显示,要么在结束之前更新,就在它关闭之前.
实例在应用程序启动附近的某处,我有:
public class SomeClass {
private SomeClass () {
myXMLParser reader = new myXMLParser();
CoolStuff fromXml = reader.readTheXml();
}
}
Run Code Online (Sandbox Code Playgroud)
使用JProgressBar显示和更新JDialog时:
public class LoadingDialog extends JDialog {
private JProgressBar progressBar;
/* ... */
public void progress() {
progressBar.setValue(progressBar.getValue() + 1);
}
}
Run Code Online (Sandbox Code Playgroud)
所以我有这个myXMLParser:
public class myXMLParser {
private LoadingDialog loadingDialog = new LoadingDialog();
public CoolStuff readTheXml() {
CoolStuff fromXml = new CoolStuff();
while(manyIterations) {
loadingDialog.progress();
fromXml.add(some() + xml() + reading()); …Run Code Online (Sandbox Code Playgroud) 我想知道如何编写以下代码,或者只是一个方法:
public void run (){
public void paint(Graphics g) {
g.fillRect(20, 20, 20, 20);
for (int i = 20; i < 1000; i++) {
g.fillRect(20, i, 20, 20);
Thread.sleep(10);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我发现我无法创建此代码的线程,因为我得到了一个非法的表达式错误启动,这是公平的,但我没有看到解决方法.
我有一个 JFrame,它根据您单击的 MenuItem 显示 JPanel。它可以工作,但是现在我需要在将 JPanel 添加到框架并显示它后调用一个方法(因为我在该面板内使用 JFreeChart 并且我必须chartPanel.repaint()在 JPanel 可见时调用):
this.getContentPane().add( myjpanel, BorderLayout.CENTER ); //this = JFrame
this.validate();
myjpanel.methodCalledOnceDisplayed();
Run Code Online (Sandbox Code Playgroud)
看起来没问题吗?真的myjpanel被展示了吗?好像不是:
public void methodCalledOnceDisplayed() {
chartPanel.repaint()
}
Run Code Online (Sandbox Code Playgroud)
这不起作用(chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0)正在抛出 IndexOutOfBoundsException)。这意味着调用重绘时 JPanel 不可见,我测试了以下内容:
public void methodCalledOnceDisplayed() {
JOptionPane.showMessageDialog(null,"You should see myjpanel now");
chartPanel.repaint()
}
Run Code Online (Sandbox Code Playgroud)
现在它起作用了,我myjpanel在警报后面看到了,正如预期的那样,重新绘制了 chartPanel 并且没有发生异常。
编辑:SSCCE(需要 jfreechart 和 jcommon:http ://www.jfree.org/jfreechart/download.html )
导入 java.awt.BorderLayout; 导入 java.awt.EventQueue; 导入 java.awt.Font; 导入 javax.swing.JButton; 导入 javax.swing.JFrame; 导入 javax.swing.JLabel; 导入 javax.swing.JOptionPane; 导入 javax.swing.JPanel; 导入 javax.swing.border.EmptyBorder; 导入 …
java ×10
swing ×9
awt ×1
concurrency ×1
debugging ×1
events ×1
jcheckbox ×1
jframe ×1
jfreechart ×1
joptionpane ×1
jprogressbar ×1
mouse-cursor ×1
paint ×1
swingworker ×1