Search code examples
javaswingsplash-screenjoptionpane

Splash Screen order is wrong


I am trying to finish this program to: 1st: Request user to enter a cellphone number in JOptionPane window 2nd: Show message "click OK to track the GPS coordinates of (input) 3rd: AFTER user clicks OK the splash screen should pop up. 4th: Splash screen should finish completely and after that the JOptionPane window should show the message "The address located within GPS coordinates is:" plus whatever fake address I enter in.

Right now the splash screen runs during everything else and is all out of order. I want the splash screen to execute after "OK" is clicked and then finish and proceed with the final JOptionPane message. Any help is greatly appreciated!! FYI-This program is intended as a fake gag joke.

  public class SplashScreen extends JWindow {

    static boolean isRegistered;
    private static JProgressBar progressBar = new JProgressBar();
    private static SplashScreen execute;
    private static int count;
    private static Timer timer1;

    public SplashScreen() {

        Container container = getContentPane();
        container.setLayout(null);

        JPanel panel = new JPanel();
        panel.setBorder(new javax.swing.border.EtchedBorder());
        panel.setBackground(Color.green);
        panel.setBounds(10, 10, 348, 150);
        panel.setLayout(null);
        container.add(panel);

        JLabel label = new JLabel("Tracking target GPS coordinates...");
        label.setFont(new Font("Verdana", Font.BOLD, 14));
        label.setBounds(15, 25, 280, 30);
        panel.add(label);

        progressBar.setMaximum(50);
        progressBar.setBounds(55, 180, 250, 15);
        container.add(progressBar);
        loadProgressBar();
        setSize(370, 215);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void loadProgressBar() {
        ActionListener al = new ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                count++;

                progressBar.setValue(count);

                System.out.println(count);

                if (count == 300) {

                    createFrame();

                    execute.setVisible(false);

                    timer1.stop();
                }

            }

            private void createFrame() throws HeadlessException {
                JFrame frame = new JFrame();
                frame.setSize(500, 500);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        };
        timer1 = new Timer(50, al);
        timer1.start();
    }

    public static void main(String[] args) {
        execute = new SplashScreen();

        String targetCell = JOptionPane.showInputDialog(null, "Enter "
                + "target cellphone number: ");
        JOptionPane.showMessageDialog(null, "Click OK to "
                + "track the GPS coordinates of " + targetCell + "...");
        JOptionPane.showMessageDialog(null, "The address located within "
                + "GPS coordinates is: " /** + "random fake address") **/); 

    }
};

Solution

  • The order in which you do things is very important. If you look at your code, the SplashScreen makes the window visible when it's created, which is a bad idea and which you've suddenly discovered.

    First, you need to change the order in which you do things, for example...

    String targetCell = JOptionPane.showInputDialog(null, "Enter "
            + "target cellphone number: ");
    JOptionPane.showMessageDialog(null, "Click OK to "
            + "track the GPS coordinates of " + targetCell + "...");
    // Show and wait for splash screen to complete
    JOptionPane.showMessageDialog(null, "The address located within "
            + "GPS coordinates is: " /**
     * + "random fake address") *
     */
    );
    

    You would also need someway to have your splash screen provide event notification of when it had completed it's task, as JWindow is none blocking.

    A simpler solution would be to display the splash screen within a modal JDialog, this would block the execution of the code at the point the splash screen was made visible, allowing you to "wait" until it had finished.

    As a general rule of thumb, you should avoid extending from top level containers like JWindow, instead prefer something like JPanel, this provides you with the flexibility to display the component in any container you want.

    It's also not the responsibility of the splash screen to launch the next window, it's only responsibility is to show the progress of it's activity (and possibly return the results of it's calculations)

    For example...

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.Font;
    import java.awt.GridBagLayout;
    import java.awt.event.ActionListener;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.border.CompoundBorder;
    import javax.swing.border.EmptyBorder;
    
    public class Main {
    
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    String targetCell = JOptionPane.showInputDialog(null, "Enter "
                            + "target cellphone number: ");
                    JOptionPane.showMessageDialog(null, "Click OK to "
                            + "track the GPS coordinates of " + targetCell + "...");
                    SplashPane.showSplashScreen();
                    JOptionPane.showMessageDialog(null, "The address located within "
                            + "GPS coordinates is: " /**
                     * + "random fake address") *
                     */
                    );
                }
            });
        }
    
        public static class SplashPane extends JPanel {
    
            private JProgressBar progressBar = new JProgressBar();
            private Timer timer1;
    
            public SplashPane() {
                setLayout(new BorderLayout(0, 4));
                setBorder(new EmptyBorder(10, 10, 10, 10));
    
                JPanel panel = new JPanel(new GridBagLayout());
                panel.setBorder(new CompoundBorder(
                        new javax.swing.border.EtchedBorder(),
                        new EmptyBorder(30, 20, 30, 20)));
                panel.setBackground(Color.green);
                JLabel label = new JLabel("Tracking target GPS coordinates...");
                label.setFont(new Font("Verdana", Font.BOLD, 14));
                panel.add(label);
                add(panel);
    
                add(progressBar, BorderLayout.SOUTH);
    
                loadProgressBar();
            }
    
            private void loadProgressBar() {
                ActionListener al = new ActionListener() {
                    private int count;
    
                    @Override
                    public void actionPerformed(java.awt.event.ActionEvent evt) {
                        count = Math.min(100, ++count);
                        progressBar.setValue(count);
    
                        System.out.println(count);
                        if (count == 100) {
                            SwingUtilities.windowForComponent(SplashPane.this).dispose();
                            timer1.stop();
                        }
                    }
                };
                timer1 = new Timer(150, al);
                timer1.start();
            }
    
            public static void showSplashScreen() {
                JDialog frame = new JDialog();
                frame.setModal(true);
                frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                frame.setUndecorated(true);
                frame.add(new SplashPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
    
        }
    }
    

    Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify