Question

I have a JProgressBar displaying a BoundedRangeModel which is extremely fine grained and I was concerned that updating it too often would slow down my computer. So I wrote a quick test program (see below) which has a 10Hz timer but each timer tick makes 10,000 calls to microtick() which in turn increments the BoundedRangeModel. Yet it seems to play nicely with a JProgressBar; my CPU is not working hard to run the program.

How does JProgressBar or DefaultBoundedRangeModel do this? They seem to be smart about how much work it does to update the JProgressBar, so that as a user I don't have to worry about updating the BoundedRangeModel's value.

package com.example.test.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoundedRangeModel;
import javax.swing.DefaultBoundedRangeModel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.Timer;

public class BoundedRangeModelTest1 extends JFrame {
    final private BoundedRangeModel brm = new DefaultBoundedRangeModel();
    final private Timer timer = new Timer(100, new ActionListener()
    {
        @Override public void actionPerformed(ActionEvent arg0) { tick(); }
    });
    public BoundedRangeModelTest1(String title) {
        super(title);

        JPanel p = new JPanel();

        p.add(new JProgressBar(this.brm));
        getContentPane().add(p);

        this.brm.setMaximum(1000000);
        this.brm.setMinimum(0);
        this.brm.setValue(0);       
    }

    protected void tick() {
        for (int i = 0; i < 10000; ++i)
        {
            microtick();
        }
    }   
    private void microtick() {
        this.brm.setValue(this.brm.getValue()+1);
    }

    public void start() 
    {
        this.timer.start();
    }

    static public void main(String[] args)
    {
        BoundedRangeModelTest1  f = 
            new BoundedRangeModelTest1("BoundedRangeModelTest1");

        f.pack();
        f.setVisible(true);     
        f.setDefaultCloseOperation(EXIT_ON_CLOSE);

        f.start();
    }
}
Was it helpful?

Solution

See the nested class DoPostEvent in the class javax.swing.Timer and the comments on the field notify.

Addendum: Events from the DefaultBoundedRangeModel are forwarded to the UI delegate by the fireStateChanged() method of JProgressBar. The events are coalesced in the EventQueue when postEvent() is invoked by repaint().

One way to follow the trail is to set a breakpoint in the UI delegate's paint() method and examine the call stack.

JProgressBar jpb = new JProgressBar(brm);
jpb.setUI(new BasicProgressBarUI());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top