JDK-8041642 : Incorrect paint of JProgressBar in Nimbus LF
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 7u45,8,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • Submitted: 2013-12-17
  • Updated: 2015-09-29
  • Resolved: 2015-05-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8 JDK 9
8u60Fixed 9 b61Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
Left edge painting of JProgressBar is changing X-anchor when doing setValue(2) vs setValue(1).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Sample code below creates a frame with a progress bar linked to a slider. There's also an sout to print current slider value. Slide and observe progress bar painting behaviour around values 0, 1 and 2.

You can easily change LF. Works perfect under System LF.

Create project with namespace progressbarTest in your IDE, paste in the source code given below in file ProgressBarTest.java. Build and run.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Painting of progress bar (orange) should stay within the valid rectangle. Seems to work for all values except '1'. Values '0', and '2-100' are ok.
ACTUAL -
JProgressBar setValue(1) has min X value too small, i.e. the orange painting is too far to the left.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package progressbartest;

import java.awt.BorderLayout;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class ProgressBarTest implements Runnable {

    private static final Logger _logger = Logger.getLogger(ProgressBarTest.class.getName());

    private static void setNimbusLF() {
        for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                try {
                    UIManager.setLookAndFeel(info.getClassName());
                } catch (Exception ex) {
                    _logger.log(Level.SEVERE, null, ex);
                }
                break;
            }
        }
    }

    private static void setSystemLF() {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ex) {
            Logger.getLogger(ProgressBarTest.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void main(String[] args) throws InterruptedException, InvocationTargetException {
        SwingUtilities.invokeAndWait(new Runnable() {

            @Override
            public void run() {
                setNimbusLF();
                //setSystemLF();
            }
        });
        new ProgressBarTest().run();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("ProgressBar Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 400);
        frame.setLocationRelativeTo(null);
        JProgressBar bar = new JProgressBar();
        JSlider slider = new JSlider();
        frame.getContentPane().add(bar, BorderLayout.NORTH);
        frame.getContentPane().add(slider, BorderLayout.SOUTH);
        link(bar, slider);
        frame.setVisible(true);
    }

    private void link(final JProgressBar bar, final JSlider slider) {
        bar.setValue(slider.getValue());
        slider.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                int value = slider.getValue();
                bar.setValue(value);
                System.out.println("value=" + value);
            }
        });
    }
}

---------- END SOURCE ----------
Comments
The bug was reproduced with JDK 9 b09, JDK 8u5 b13, JDK 7u55 b13.
23-04-2014