Reputation: 497
When this code is run everything works fine, but problem comes in main when I change the code inside to be used with 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();}
}
}
changing the main method to
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();
}
}
});
}
No exception but it doesn't work as expected and as you all know using EventQueue
is preferable than working inside a main method due to EDT.
But the following works.
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();
}
}
Though progress bar gets null at some point and oops! NullPointerException
is thrown. As you can see am making a custom SplashWindow
instead of the built in one. Need help and please don't point out some libraries.
Upvotes: 1
Views: 307
Reputation: 347332
There's nothing wrong with EventQueue.invokeLater
, it's all in how you are using it.
This...
EventQueue.invokeLater(new Runnable() {
public void run() {
//...
}
});
is saying, at some point in the future, do this. BUT, you immediately follow it up with...
for (int i = 0; i < 100; i++) {
frame.setProgress(i);
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
which is probably going to execute BEFORE invokeLater
has had a chance to run.
A overall better solution would be to use SwingWorker
instead and start it within the EventQueue.invokeLater
, once you have ensured that the state of the UI has been established.
Remember, Swing is not only single threaded, it is NOT thread safe. This means that not only should you not block the main UI thread (ie the Event Dispatching Thread), should also not update the UI, or anything it relies on, from outside of it
See Worker Threads and SwingWorker for more details
Upvotes: 3