运行此代码时一切正常,但是当我更改内部代码以与 EventQueue.invokeLater()
一起使用时,主要问题出现了
package dav.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JProgressBar;
public class SplashWindow extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JProgressBar progressBar;
/**
* Launch the application.
*/
public static void main(String[] args) {
//from here...
final SplashWindow frame = new SplashWindow(); frame.setLocationRelativeTo(null);
frame.setVisible(true);
for (int i = 0; i < 100; i++) {
frame.setProgress(i);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
//to here...
}
/**
* Create the frame.
*/
public SplashWindow() {
setUndecorated(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JPanel panel = new JPanel();
contentPane.add(panel, BorderLayout.CENTER);
progressBar = new JProgressBar();
progressBar.setMaximum(100);
progressBar.setValue(0);
progressBar.setForeground(Color.CYAN);
panel.setBackground(Color.BLUE);
GroupLayout gl_panel = new GroupLayout(panel);
gl_panel.setHorizontalGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel.createSequentialGroup().addContainerGap()
.addComponent(progressBar, GroupLayout.DEFAULT_SIZE, 420, Short.MAX_VALUE).addContainerGap()));
gl_panel.setVerticalGroup(gl_panel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_panel
.createSequentialGroup().addGap(245).addComponent(progressBar, GroupLayout.PREFERRED_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap(31, Short.MAX_VALUE)));
panel.setLayout(gl_panel);
}
public void setProgress(int i) {
progressBar.setValue(i);
if (i+1>=progressBar.getMaximum()){
dispose();}
}
}
将主要方法更改为
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
final SplashWindow frame = new SplashWindow(); frame.setLocationRelativeTo(null);
frame.setVisible(true);
for (int i = 0; i < 100; i++) {
frame.setProgress(i);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
没有异常(exception),但它没有按预期工作,而且众所周知,由于 EDT,使用 EventQueue
比在 main 方法中工作更可取。
但下面的工作。
final SplashWindow frame = new SplashWindow();
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
for (int i = 0; i < 100; i++) {
frame.setProgress(i);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
尽管进度条在某些时候变为空并且哎呀! NullPointerException
被抛出。如您所见,我正在制作自定义 SplashWindow
而不是内置的。需要帮助,请不要指出一些库。
最佳答案
EventQueue.invokeLater
没有错,关键在于您如何使用它。
这...
EventQueue.invokeLater(new Runnable() {
public void run() {
//...
}
});
是说,在未来的某个时候,这样做。但是,您立即跟进......
for (int i = 0; i < 100; i++) {
frame.setProgress(i);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
它可能会在 invokeLater
有机会运行之前执行。
一个总体上更好的解决方案是改用 SwingWorker
并在 EventQueue.invokeLater
中启动它,一旦您确保 UI 的状态已经建立。
请记住,Swing 不仅是单线程的,而且不是线程安全的。这意味着你不仅不应该阻塞主 UI 线程(即事件调度线程),也不应该从它的外部更新 UI 或它依赖的任何东西
参见 Worker Threads and SwingWorker了解更多详情
关于java - EventQueue.invokeLater() 有一些错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58193149/