Search code examples
javaswingjprogressbar

JProgressBar not visible until told to show


I'm trying to make an application which shows a JProgressBar only while it is performing actions. My problem is, when the program is first opened, I set the JProgressBar visibility to false, then to true when an action is being performed and after it is done, back to false. It seems like it would work, and it does, just not when I make it not visible by default. If the visibility is true by default then it works well, but that's not quite what I want. How could I make it so that it isn't visible until I set it to be visible?

SSCCE just incase my question wasn't clear enough:

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

public class SmileBack {

    private JFrame frame;

    private JPanel panel, container;

    private JButton loadButton;

    private JProgressBar progressBar;

    public static void main(String[] arguments) {
        new SmileBack().constructFrame();
    }

    public void constructFrame() {
        frame = new JFrame("RSTracker");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(getContentPane());
        frame.pack();
        frame.setVisible(true);
    }

    public JPanel getContentPane() {
        panel = new JPanel(new BorderLayout());

        progressBar = new JProgressBar();
        progressBar.setIndeterminate(true);
        //progressBar.setVisible(false); // doesn't work when this is uncommented

        loadButton = new JButton("Load memberlist");
        loadButton.setEnabled(true);
        loadButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        progressBar.setVisible(true);
                        // do my stuff here...
                        try {
                            Thread.sleep(2000); // just for the sake of example
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        progressBar.setVisible(false);
                    }

                }).start();
            }

        });

        container = new JPanel(new FlowLayout());
        container.add(loadButton);
        container.add(progressBar);

        panel.add(container);

        return panel;
    }

}

Ignore the name, I was listening to that song while creating this. :)


Solution

  • This is probably not the way it should be designed, but this code fixes the problem while still using the natural size (pack()) needed to display the button and progress bar. This is achieved by setting the progress bar to invisible after pack is called, but before setting the GUI visible.

    import java.awt.BorderLayout;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    
    public class SmileBack {
    
        private JFrame frame;
    
        private JPanel panel, container;
    
        private JButton loadButton;
    
        private JProgressBar progressBar;
    
        public static void main(String[] arguments) {
            new SmileBack().constructFrame();
        }
    
        public void constructFrame() {
            frame = new JFrame("RSTracker");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(getContentPane());
            // after this, everything is instantiated;
            frame.pack();
            setProgressBarVisibility(false);
            frame.setVisible(true);
        }
    
        public void setProgressBarVisibility(boolean visible) {
            progressBar.setVisible(visible);
        }
    
        public JPanel getContentPane() {
            panel = new JPanel(new BorderLayout());
    
            progressBar = new JProgressBar();
            progressBar.setIndeterminate(true);
    
            loadButton = new JButton("Load memberlist");
            loadButton.setEnabled(true);
            loadButton.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    new Thread(new Runnable() {
    
                        @Override
                        public void run() {
                            progressBar.setVisible(true);
                            // do my stuff here...
                            try {
                                Thread.sleep(2000); // just for the sake of example
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            progressBar.setVisible(false);
                        }
    
                    }).start();
                }
    
            });
    
            container = new JPanel(new FlowLayout());
            container.add(loadButton);
            container.add(progressBar);
    
            panel.add(container);
    
            return panel;
        }
    }