0

In the following application I have put a button ,clicking on which makes the GlassPane visible and a Thread starts which updates the Progress bar value.Below is the code:-

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;


public class GlassPaneDownload extends JFrame implements Runnable{
Thread t;
CustomGlassPane jp;

public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable(){public void run(){new GlassPaneDownload();}});
}

public GlassPaneDownload(){
super("Glass Pane Download Simulation");
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new FlowLayout());    

jp=new CustomGlassPane();

jp.setOpaque(false);
setGlassPane(jp);


JButton btn=new JButton("Click Here");
btn.addActionListener(new ActionListener(){public void actionPerformed(ActionEvent e){
    //Make Glass Pane visible
    jp.setVisible(true);
    //Start Thread to update Progress Bar
    t=new Thread();
    t.start();
}});
add(btn);
setVisible(true);
}
public void run(){
for(int i=1;i<=100;i++)
{
    jp.setProgress(i);
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
t=null;
}
}

class CustomGlassPane extends JComponent
{


    private final float pattern[]=new float[]{0.0f,0.499f,0.50f,1.0f};
    private final Color color[]=new Color[]{Color.WHITE,Color.GRAY,Color.BLACK,Color.LIGHT_GRAY};
    private int progress,oldProgress;


    public void paintComponent(Graphics g1)
    {
        super.paintComponent(g1);
        g1.setColor(new Color(1.0f,1.0f,1.0f,0.7f));
        g1.fillRect(0, 0, getWidth(), getHeight());
        g1.setColor(new Color(200,200,255));
        g1.drawRect(100,100,200,20);

        LinearGradientPaint p=new LinearGradientPaint(100,100,200,20,pattern,color);
        Graphics2D g2=(Graphics2D)g1;
        g2.setPaint(p);
        g2.fillRect(100, 100,progress*2, 20);
    }
    public void setProgress(int prog)
    {
        progress=prog;
        repaint(100,100,200,20);
        //repaint();
    }

}

But,though the GlassPane gets visible but the ProgressBar is not updating. Need Help friends.

Naveen
  • 7,944
  • 12
  • 78
  • 165
  • see this question, [how can you make a progress bar without using JProgressBar?](http://stackoverflow.com/questions/14036173/how-can-you-make-a-progress-bar-without-using-jprogressbar), then works layed on GlassPane as expected, I vote to close this question as duplicate – mKorbel Jan 03 '13 at 13:00
  • It's not exact duplicate because the issue with code is of a different nature. It is, however, a helpful link to the right way. – Marko Topolnik Jan 03 '13 at 13:01

1 Answers1

3

This is a classical mistake: you are blocking the EDT (Event Dispatching Thread) with a loop over a Thread.sleep(). The EDT dispatches all GUI events: paint-events, mouse-events, key-events, action-events etc... Since you are looping and sleeping in the EDT (during an ActionEvent), it prevents the display from refreshing (I bet that your GUI becomes unresponsive after you click the button). So

  • Rule #1: do not block the EDT
  • Rule #2: DO NOT BLOCK THE EDT, which leads directly to
  • Rule #3: do not sleep()in the EDT, and
  • Rule #4: do not perform any lengthy-operation in the EDT

To work around this problem, use SwingWorker or javax.swing.Timer. This can also work with traditional Thread's and Executors (thread-pools) but you have to make sure that all your attempts to modify the GUI are performed in the EDT.

You may want to have a look at this example which shows how to combine a JProgressBar and a SwingWorker

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • @Guillaume Pole :What if I create a new class implementing Runnable and create its object in the button's ActionListener.? Will it also run on EDT? – Naveen Jan 03 '13 at 13:23
  • 2
    @Naveen a `Runnable` on its own does not create a new Thread. `Thread t = new Thread(someRunnable); t.start();` does. But I would really consider using `SwingWorker` or `javax.swing.Timer`. If you all you need is to update a progress bar every 100ms, then `javax.swing.Timer` will do a perfect job (and it runs on the EDT too). If you need to perform lengthy-operation, `SwingWorker` will help you in separating "lengthy-operations" from "UI-update operations" and combine them together. – Guillaume Polet Jan 03 '13 at 13:33