newbie
newbie

Reputation: 14950

Java Swing Utilities

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

Answers (1)

MadProgrammer
MadProgrammer

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....

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

Related Questions