Reputation: 14950
I want to create a loading message that will popup on the screen while information is being loaded. I will call the initLoadingPanel() method for it so that the JFrame will be visible. My problem is how can I close it?
My code is below.
public class DataMigration extends JFrame{
private JFrame frmDataMigration;
private JFrame loader;
private JButton btnProcess;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
DataMigration window = new DataMigration();
window.frmDataMigration.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public DataMigration() {
initialize();
}
private void initialize() {
LoggerImp.startLog(CLASS_NAME, "initialize()");
frmDataMigration = new JFrame();
btnProcess = new JButton("Load");
btnProcess.setEnabled(false);
btnProcess.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
SwingWorker <CSV, CSV> worker = new SwingWorker<CSV, CSV>() {
@Override
protected CSV doInBackground() throws Exception {
return FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText());
}
@Override
protected void done() {
try {
csv = doInBackground();
generateTableList(csv.getCsvTitle(), stateController.getFieldNames());
} catch (ExecutionException ex) {
ex.printStackTrace();
} catch (Exception e){
}
loader.dispose();
}
};
worker.execute();
}
});
frmDataMigration.getContentPane().add(btnProcess);
}
public void initLoadingPanel(){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
loader = new JFrame("Loading....");
ImageIcon img = new ImageIcon("loader.gif");
loader.add(new JLabel(" Loading...", img, JLabel.CENTER));
loader.setAlwaysOnTop(true);
loader.pack();
loader.setSize( 448, 497);
loader.setVisible(true);
loader.setLocationRelativeTo(null);
}
});
}
Upvotes: 0
Views: 535
Reputation: 347204
Generally, you should only need to call loader.dispose()
or loader.setVisible(false)
, this then raises the question of, how are you loading your resources?
You will, likely, need to pass a reference of loader
to the this part of your code, so when it's finished, you can dispose of the frame.
Because the frame is decorated, the user could simply hit the "[x]" button and close the window, while you can set the frames defaultCloseOperation
to DO_NOTHING_ON_CLOSE
, it still looks weird.
You could remove the frame decorations using JFrame#setUndecorated
Because loader
extends from JFrame
it's still possible for the user to interact with the parent window (if one is visible), a better solution might be to use a JDialog
instead and make it modal.
You might also consider having a look at How to Create a Splash Screen for some other ideas
Updated
You're shadowing your variables...
First you declare loader
as a instance field of DataMigration
public class DataMigration extends JFrame{
//...
private JFrame loader;
But then re-declare it within the run
method of your Runnable
....
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame loader = new JFrame("Loading....");
This means that the instance field is still null, try...
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
loader = new JFrame("Loading....");
instead...
Also...
public void actionPerformed(ActionEvent arg0) {
initLoadingPanel();
csv = FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText());
generateTableList(csv.getCsvTitle(), stateController.getFieldNames());
loader.dispose();
}
Isn't going to do what you think it should...you "might" get lucky and the loader
frame will appear, but it's likely that it won't because you're blocking the Event Dispatching Thread.
Instead, you should consider using a SwingWorker
....
initLoadingPanel();
SwingWorker worker = new SwingWorker<CVS, CVS>() {
@Override
protected CVS doInBackground() throws Exception {
return FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText());
}
@Override
protected void done() {
try {
cvs = get();
generateTableList(csv.getCsvTitle(), stateController.getFieldNames());
} catch (ExecutionException ex) {
ex.printStackTrace();
}
loader.dispose();
}
};
worker.execute();
(I don't know what type cvs
is, so I'm guessing...
This will ensure that your UI will remain responsive while the data is loaded...
Take a look at Concurrency in Swing
Update with a working example....
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
public class DataMigration extends JFrame {
private JFrame frmDataMigration;
private JFrame loader;
private JButton btnProcess;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
DataMigration window = new DataMigration();
window.frmDataMigration.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public DataMigration() {
initialize();
}
private void initialize() {
frmDataMigration = new JFrame();
btnProcess = new JButton("Load");
btnProcess.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
initLoadingPanel();
SwingWorker worker = new SwingWorker() {
@Override
protected Object doInBackground() throws Exception {
Thread.sleep(5000);
return "This is a test value used to highlight the example";
}
@Override
protected void done() {
try {
get();
} catch (ExecutionException ex) {
} catch (InterruptedException ex) {
}
loader.dispose();
btnProcess.setEnabled(true);
}
};
worker.execute();
btnProcess.setEnabled(false);
}
});
frmDataMigration.getContentPane().add(btnProcess);
frmDataMigration.setDefaultCloseOperation(EXIT_ON_CLOSE);
frmDataMigration.pack();
frmDataMigration.setLocationRelativeTo(null);
}
public void initLoadingPanel() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
loader = new JFrame("Loading....");
ImageIcon img = new ImageIcon("loader.gif");
loader.add(new JLabel(" Loading...", img, JLabel.CENTER));
loader.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
loader.setAlwaysOnTop(true);
loader.pack();
loader.setSize(448, 497);
loader.setVisible(true);
loader.setLocationRelativeTo(null);
}
});
}
}
Upvotes: 5