JProgressBar does not update within the loop

喜夏-厌秋 提交于 2019-12-12 15:56:02

问题


I am currently self-studying Java. I've been trying different things like JRadioButtons, JcomboBoxes etc. Now, I'm trying to use JProgressBars but it doesn't seem to work properly.

Relevant piece of code:

JProgressBar progress;
JButton button;     //Fields of the class

progress=new JProgressBar(JProgressBar.HORIZONTAL,0,100);
button=new JButton("Done");    //Done from methods

progress.setValue(0);
progress.setStringPainted(true);
progress.setBorderPainted(true);  //Also done from methods

button.addActionListener(this);   //Also done from methods

When button is clicked, I want to show the JProgressBar go from 0% to 100%. Here is the relevant portion of the actionPerformed method:

public void actionPerformed(ActionEvent e)
{

        for(int i=0;i<=progress.getMaximum();i++)
        {
            progress.setValue(i);
            /*try{
                Thread.sleep(10);
            }catch(InterruptedException ex)
            {
                System.err.println("An error occured:"+ex);
                ex.printStackTrace();
            }*/
        }


        progress.setValue(progress.getMinimum());
}

I've added both progress and button into a JPanel and the panel into a JFrame on which I use setVisible(true);.

The problem here is, whenever I press the JButton button, the JProgressBar progress does not go from 0% to 100%. Instead, nothing happens. If I uncomment the try...catch block, and then press button, the program "freezes" for a moment and then continues. This time too, The JProgressBar stays at 0% and I never see it moving. I've also tried a repaint(); just after the try...catch block but the same thing happened.

I've tried adding

System.out.println(i+"");

inside the for loop in actionPerformed and this printed numbers 0 to 100 in the terminal. So, I'm sure that the loop runs.

How can I solve this problem?


回答1:


  • Swing is single threaded,

  • all updates must be done on EDT,

  • all events in current EDT are painted in GUI in one moment,

  • Thread.sleep to lock execution of event in EDT, repaint can be painted at the end of for_loop, after all lock(s) from Thread.sleep are executed, more in Oracle trail - Concurency in Swing and EventDispatchThread


output from AWT (Swing) Listener - ActionListener, should be done if all events inside actionPerformed are executed, then there is executed only progress.setValue(progress.getMinimum());, doesn't matter if is there Thread.sleep or not

public void actionPerformed(ActionEvent e) -> progress.setValue(progress.getMinimum());

  • use SwingWorker or Runnable#Thread with progress.setValue(i); wrapped into invokeLater

  • for better help sooner post an SSCCE/MCVE, short, runnable, compilable




回答2:


You have to put following piece of code to new thread

public void actionPerformed(ActionEvent e)
{

    for(int i=0;i<=progress.getMaximum();i++)
    {
        progress.setValue(i);
        /*try{
            Thread.sleep(10);
        }catch(InterruptedException ex)
        {
            System.err.println("An error occured:"+ex);
            ex.printStackTrace();
        }*/
    }


    progress.setValue(progress.getMinimum());
}

Something like this

public void actionPerformed(ActionEvent e)
{
    new Thread(){
        public void run(){
            for(int i=0;i<=progress.getMaximum();i++)
            {
                progress.setValue(i);
                try{
                    sleep(10);
                }catch(InterruptedException ex)
                {
                    System.err.println("An error occured:"+ex);
                    ex.printStackTrace();
                }
            }
        }
    }.start();
    progress.setValue(progress.getMinimum());
}

Not tested, progress instance should be final maybe




回答3:


As far as your code goes, it all looks legit. Doesn't seem to give any issue regardless of not initiating a thread.

What I suggest you do is remove this:

//for testing purposes
progress.setValue(progress.getMinimum());

And then make the value of the progress bar 50. Remove the thread code, and use the for loop with the condition "< 50".

If all else fails, this will surely shed some light: JProgress Bar: Working!

Let me know of the outcome.



来源:https://stackoverflow.com/questions/29727991/jprogressbar-does-not-update-within-the-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!