javaswingjprogressbar

In this case, how should I access to the JProgressBar from another class?


I am currently practicing OOP with Java.

I have created a GUI project via WindowBuilder with Eclipse IDE and below is the result.

private JFrame frame;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Example window = new Example();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public Example() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
    JProgressBar progressBar = new JProgressBar();
    frame.getContentPane().add(progressBar, BorderLayout.CENTER);
}

What I am trying to do is to connect the JProgressBar to another class that has the actual task, to show the progress.

For example, if the other class contains the following code:

int i = 0;
while(i <= 100) {
    progressBar.setValue(i);
    i++;
}

how should I change the progressBar.setValue(i); part?


Solution

  • Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Concurrency in Swing section.

    Here's the simplest working example I could create. As you can see in the picture, I caught the JProgressBar in the middle.

    Example

    Each time you press the button, the progress bar will count from 0 to 100, one unit every 100 milliseconds.

    In order to access the progress bar, you have to make it a class field or variable. You can then access the class field with a setter. Getters and setters are a basic Java concept. You can see another example of a plain Java getter/setter class in my JProgressBarModel class.

    I used a Swing Timer to add a delay to the updating of the progress bar so you can see the bar update and simulate an actual long-running task. The actual work takes place in the WorkListener class. Because the code is inside an ActionListener, the Swing update of the progress bar takes place on the Event Dispatch Thread.

    Here's the complete runnable code. I made all the additional classes inner classes so I could post the code as one block.

    import java.awt.BorderLayout;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.BorderFactory;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class JProgressBarExample implements Runnable {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new JProgressBarExample());
        }
    
        private JProgressBar progressBar;
    
        private final JProgressBarModel model;
    
        public JProgressBarExample() {
            this.model = new JProgressBarModel();
        }
    
        @Override
        public void run() {
            JFrame frame = new JFrame("Progress Bar Example");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.add(createMainPanel(), BorderLayout.CENTER);
    
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        private JPanel createMainPanel() {
            JPanel panel = new JPanel(new FlowLayout());
            panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    
            progressBar = new JProgressBar();
            panel.add(progressBar);
    
            JButton button = new JButton("Start Process");
            button.addActionListener(event -> {
                model.setIndex(0);
                setValue();
                Timer timer = new Timer(100, new WorkListener(this, model));
                timer.start();
            });
            panel.add(button);
    
            return panel;
        }
    
        public void setValue() {
            progressBar.setValue(model.getIndex());
        }
    
        public class WorkListener implements ActionListener {
    
            private final JProgressBarExample view;
    
            private final JProgressBarModel model;
    
            public WorkListener(JProgressBarExample view, JProgressBarModel model) {
                this.view = view;
                this.model = model;
            }
    
            @Override
            public void actionPerformed(ActionEvent event) {
                Timer timer = (Timer) event.getSource();
                int index = model.getIndex() + 1;
                model.setIndex(index);
                view.setValue();
                if (index >= 100) {
                    timer.stop();
                }
            }
    
        }
    
        public class JProgressBarModel {
    
            private int index;
    
            public int getIndex() {
                return index;
            }
    
            public void setIndex(int index) {
                this.index = index;
            }
    
        }
    
    }