1

I'm trying to add a JProgressBar to a simple program just to learn. So far i can display it, but it adds multiple instance while i want just one to show.enter image description here

Here's the code :

package package1;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

import javax.swing.JPanel;
import javax.swing.JProgressBar;

public class Opening extends JPanel {
    private JProgressBar loadingBar;
    private Thread t;

public void paintComponent(Graphics g)
{
    super.paintComponent(g);    
    //Loading bar
    bar();
}

private void bar()
{
    loadingBar = new JProgressBar();
    t = new Thread(new LoadMyBar());

    this.add(loadingBar).setLocation(25, 600);
    loadingBar.setSize(625, 25);
    loadingBar.setStringPainted(true);
    loadingBar.setValue(0);
    loadingBar.setMinimum(0);
    loadingBar.setMaximum(100);
    t.start();
}

class LoadMyBar implements Runnable
{
    public void run(){
        for(int i = loadingBar.getMinimum(); i <= loadingBar.getMaximum(); i++)
        {
            loadingBar.setValue(i);
            try
            {
                t.sleep(1000);
            }catch(InterruptedException e)
            {
                e.printStackTrace();
            }   
        }
    }
}

}

Any idea on what i'm doing wrong?

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Chax
  • 1,041
  • 2
  • 14
  • 36

2 Answers2

5

You're calling bar() inside of the paintComponent(Graphics g) method. This method is responsible for drawing the component and can be called potentially many times and not in your control. Don't do that, but rather call it once in a constructor or some other location where it can be called just once.

You're also setting the JProgressBar's value off of the Swing event thread, something that can be dangerous to do. Use a Swing Timer instead or use a SwingWorker's progress property together with a PropertyChangeListener.

e.g.,

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

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

@SuppressWarnings("serial")
public class Opening extends JPanel {
   private static final int TIMER_DELAY = 1000;
   private JProgressBar loadingBar;
   private Timer t = new Timer(TIMER_DELAY, new TimerListener());

   public Opening() {
      bar();
   }

   private void bar() {
      loadingBar = new JProgressBar();
      this.add(loadingBar);
      loadingBar.setStringPainted(true);
      loadingBar.setValue(0);
      loadingBar.setMinimum(0);
      loadingBar.setMaximum(100);
      t.start();
   }

   private class TimerListener implements ActionListener {
      int value = 0;

      @Override
      public void actionPerformed(ActionEvent e) {
         if (value <= 100) {
            loadingBar.setValue(value);
            value++;
         } else {
            // value > 100
            ((Timer) e.getSource()).stop(); // stop timer
         }
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("Opening");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(new Opening());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • If I want to add a JProgressBar to a JPanel how should I proceed then? I need the JPanel because it display some graphical content(did'nt put the code cause it's more readable that way). – Chax Sep 23 '14 at 21:44
  • @Chax: for instance, see example above. And don't set sizes of anything. Instead use layout managers for that. – Hovercraft Full Of Eels Sep 23 '14 at 21:44
1

You are creating the JProgressBar and adding it to your class Opening in the method paintComponent(). paintComponent() is called every time, the component needs to draw itself.

This can be after resizing the window (JFrame) or some other application overlapping your application.

You should move the initialization to the constructor of Opening.

See http://docs.oracle.com/javase/tutorial/uiswing/painting/closer.html

Markus Patt
  • 467
  • 3
  • 11