Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5035852

IllegalArgumentException thrown by BasicProgressBarUI.paintDeterminate()

XMLWordPrintable

      Name: rmT116609 Date: 04/21/2004


      FULL PRODUCT VERSION :
      java version "1.4.2_04"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
      Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows 2000 [Version 5.00.2195]

      A DESCRIPTION OF THE PROBLEM :
      Under some conditions BasicProgreessBar.paintDeterminate() creates a BasicStroke passing a negative value for the width argument. BasicStroke's constructor then throws an IIllegalArgumentException :

      java.lang.IllegalArgumentException: negative width

      at java.awt.BasicStroke.<init>(BasicStroke.java:181)

      at java.awt.BasicStroke.<init>(BasicStroke.java:254)

      at javax.swing.plaf.basic.BasicProgressBarUI.paintDeterminate(BasicProgressBarUI.java:641)

      at javax.swing.plaf.metal.MetalProgressBarUI.paintDeterminate(MetalProgressBarUI.java:45)

      at javax.swing.plaf.basic.BasicProgressBarUI.paint(BasicProgressBarUI.java:335)

      at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)

      at javax.swing.JComponent.paintComponent(JComponent.java:541)

      at javax.swing.JComponent.paint(JComponent.java:808)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JLayeredPane.paint(JLayeredPane.java:557)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4802)

      at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4748)

      at javax.swing.JComponent.paint(JComponent.java:798)

      at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)

      at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)

      at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)

      at java.awt.Container.paint(Container.java:1312)

      at javax.swing.JDialog.update(JDialog.java:467)

      at sun.awt.RepaintArea.paint(RepaintArea.java:169)

      at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:260)

      at java.awt.Component.dispatchEventImpl(Component.java:3678)

      at java.awt.Container.dispatchEventImpl(Container.java:1627)

      at java.awt.Window.dispatchEventImpl(Window.java:1606)

      at java.awt.Component.dispatchEvent(Component.java:3477)

      at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)

      at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)

      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)

      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:141)

      at java.awt.Dialog$1.run(Dialog.java:540)

      at java.awt.Dialog.show(Dialog.java:561)

      at java.awt.Component.show(Component.java:1133)

      at java.awt.Component.setVisible(Component.java:1088)

      at ProgressPanel.setVisibleInDispatchThread(ProgressPanel.java:97)

      at ProgressPanel.access$1(ProgressPanel.java:14)

      at ProgressPanel$3.run(ProgressPanel.java:111)

      at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)

      at java.awt.EventQueue.dispatchEvent(EventQueue.java:454)

      at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)

      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)

      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)

      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)

      at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the attached program. Resize the dialog making the scroll bar height become zero, and the exception willl be thrown,. you may have to try resizing a few times.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Even if it is possible to prevent the progress bar height from becoming 0 by setting a min size, if the user doesn't set it the program should not throw this exception.
      ACTUAL -
      an exception is thrown

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.lang.IllegalArgumentException: negative width

      at java.awt.BasicStroke.<init>(BasicStroke.java:181)

      at java.awt.BasicStroke.<init>(BasicStroke.java:254)

      at javax.swing.plaf.basic.BasicProgressBarUI.paintDeterminate(BasicProgressBarUI.java:641)

      at javax.swing.plaf.metal.MetalProgressBarUI.paintDeterminate(MetalProgressBarUI.java:45)

      at javax.swing.plaf.basic.BasicProgressBarUI.paint(BasicProgressBarUI.java:335)

      at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)

      at javax.swing.JComponent.paintComponent(JComponent.java:541)

      at javax.swing.JComponent.paint(JComponent.java:808)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paint(JComponent.java:817)

      at javax.swing.JLayeredPane.paint(JLayeredPane.java:557)

      at javax.swing.JComponent.paintChildren(JComponent.java:647)

      at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4802)

      at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4748)

      at javax.swing.JComponent.paint(JComponent.java:798)

      at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)

      at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)

      at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)

      at java.awt.Container.paint(Container.java:1312)

      at javax.swing.JDialog.update(JDialog.java:467)

      at sun.awt.RepaintArea.paint(RepaintArea.java:169)

      at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:260)

      at java.awt.Component.dispatchEventImpl(Component.java:3678)

      at java.awt.Container.dispatchEventImpl(Container.java:1627)

      at java.awt.Window.dispatchEventImpl(Window.java:1606)

      at java.awt.Component.dispatchEvent(Component.java:3477)

      at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)

      at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)

      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)

      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:141)

      at java.awt.Dialog$1.run(Dialog.java:540)

      at java.awt.Dialog.show(Dialog.java:561)

      at java.awt.Component.show(Component.java:1133)

      at java.awt.Component.setVisible(Component.java:1088)

      at ProgressPanel.setVisibleInDispatchThread(ProgressPanel.java:97)

      at ProgressPanel.access$1(ProgressPanel.java:14)

      at ProgressPanel$3.run(ProgressPanel.java:111)

      at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)

      at java.awt.EventQueue.dispatchEvent(EventQueue.java:454)

      at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)

      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)

      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)

      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)

      at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)


      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      import javax.swing.*;
      import java.awt.*;
      import java.awt.event.*;
      import java.io.File;

      class UserAbortException extends Exception {
        public UserAbortException(String msg) {
          super(msg);
        }
        public UserAbortException() {
        }
      }

      public class ProgressPanel extends JDialog implements WindowListener {
        private final static int WIDTH = 300;
        private final static int HEIGHT = 200;
        private boolean shouldAbort = false;

        private JLabel messageLabel;
        private JProgressBar progress;
        private JButton abortBut;
        private static ProgressPanel panel;

        public ProgressPanel(String title) {
           super((JFrame)null, title, true);
           setSize(WIDTH, HEIGHT);
           setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
           this.addWindowListener(this);
           Dimension bounds = Toolkit.getDefaultToolkit().getScreenSize();
           setLocation((bounds.width-WIDTH)/2, (bounds.height-HEIGHT)/2);
           Container contentPane = getContentPane();
           contentPane.setLayout(new BorderLayout());
           JPanel mainPanel = new JPanel();
           mainPanel.setLayout(new BorderLayout());
           mainPanel.setBorder(BorderFactory.createEtchedBorder());
           messageLabel = new JLabel();
           progress = new JProgressBar();
           progress.setMinimum(0);
           progress.setMaximum(100);
           JPanel p2 = new JPanel();
           p2.setLayout(new GridLayout(2, 1));
           p2.add(messageLabel);
           p2.add(progress);
           JPanel pp = new JPanel();
           pp.setLayout(new GridLayout(3, 1));
           pp.add(new JPanel());
           pp.add(p2);
           pp.add(new JPanel());
           mainPanel.add(pp, BorderLayout.CENTER);

           contentPane.add(mainPanel, BorderLayout.CENTER);
           abortBut = new JButton("Abort");
           abortBut.addActionListener(new ActionListener(){
             public void actionPerformed(ActionEvent ev) {
               shouldAbort = true;
             }
           });
           JPanel pp1 = new JPanel();
           pp1.setLayout(new FlowLayout());
           pp1.add(abortBut);
           contentPane.add(pp1, BorderLayout.SOUTH);
        }

        private void setVisibleInDispatchThread(boolean v) {
          if (! v) {
            ActionListener[] al = abortBut.getActionListeners();
            for(int i=0; i<al.length; i++)
              abortBut.removeActionListener(al[i]);
            getContentPane().removeAll();
            // need to set bar to determinate, otherwise timer thread still points to them
            if (progress != null)
              progress.setIndeterminate(false);
            synchronized(ProgressPanel.class) {
              panel = null;
            }
          } else {
            synchronized(ProgressPanel.class) {
              if (panel != null)
                return;
              panel = this;
            }
          }
          super.setVisible(v);
        }

        /**
         * shows/hide the dialog. This method invokes the actual setVisible()
         * through SwingUtilities.invokeLater(), regardless of whether the
         * current thread is the AWT event dispatch thread or not. This has
         * the effect of not blocking the AWT event dispatch thread, so that
         * the modality of the dialog consist in blocking the input to the parent,
         * but not blocking the thread invoking setVisible().
         */
        public void setVisible(final boolean v) {
          SwingUtilities.invokeLater(new Runnable(){
            public void run() {
              setVisibleInDispatchThread(v);
            }
          });
        }


        public void reportProgress(final String msg) throws UserAbortException {
          reportProgress(msg, -1);
          if (shouldAbort){
            shouldAbort = false;
            throw new UserAbortException();
          }
        }

        public void reportProgress(final String msg, final float percent) throws UserAbortException {
          if (shouldAbort){
            shouldAbort = false;
            throw new UserAbortException();
          }
          if (! SwingUtilities.isEventDispatchThread()) {
            SwingUtilities.invokeLater(new Runnable(){
              public void run() {
                reportProgressInDispatchThread(msg, percent);
              }
            });
          } else
            reportProgressInDispatchThread(msg, percent);
        }

        private void reportProgressInDispatchThread(String message, float percent) {
          if (message != null)
            messageLabel.setText(message);
          if (progress != null) {
            if (percent != -1.0) {
              progress.setIndeterminate(false);
              progress.setValue((int )(percent*100));
            } else {
              progress.setIndeterminate(true);
            }
          }
        }


        public boolean aborting() {
          return shouldAbort;
        }


        public void windowClosed(WindowEvent e) {
          if(abortBut.isEnabled())
             shouldAbort = true;
          else
            shouldAbort = false;
        }

        public void windowClosing(WindowEvent e){
          if(abortBut.isEnabled())
             shouldAbort = true;
          else
            shouldAbort = false;
        }

        public void windowActivated(WindowEvent e){}
        public void windowDeactivated(WindowEvent e) {}
        public void windowDeiconified(WindowEvent e){}
        public void windowIconified(WindowEvent e) {}
        public void windowOpened(WindowEvent e){}


        public static void main(String args[]) {
          ProgressPanel p = new ProgressPanel("test");
          p.setVisible(true);
          try {
            for(int i=0; i<1000; i++) {
              p.reportProgress((i/10)+"% done", i/1000f);
              Thread.sleep(100);
            }
          }catch(UserAbortException ex) {
            System.out.println("User abort");
          }catch(Exception ex) {
            ex.printStackTrace();
          }finally {
            p.setVisible(false);
          }
        }

      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I guess setting the JProgressBar min size should prevent the problem
      (Incident Review ID: 250290)
      ======================================================================

            alexsch Alexandr Scherbatiy
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: