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

DEA:Canvas repaint,a performance issue

XMLWordPrintable

    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      JDK java version "1.6.0_13"

      ADDITIONAL OS VERSION INFORMATION :
      Windows XP proff

      A DESCRIPTION OF THE PROBLEM :
      When compared to swing components performance of Canvas is poor .
      It does not repaint the UI properly .


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      run the code in the source code section ,we can see that Canvas is not repainted.
      The main issue is that the Canvas' paint() method is not getting called whereas the Jpanel's paint() method is.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Canvas should also repaint as JPanel
      ACTUAL -
      The main issue is that the Canvas' paint() method is not getting called whereas the Jpanel's paint() method is.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      no error message

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      import java.awt.Canvas;
      import java.awt.Component;
      import java.awt.Dimension;
      import java.awt.Graphics;
      import java.awt.event.MouseAdapter;
      import java.awt.event.MouseEvent;
      import java.awt.event.WindowAdapter;
      import java.awt.event.WindowEvent;
      import javax.swing.BorderFactory;
      import javax.swing.BoxLayout;
      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.JSplitPane;

      public class HeavyWeightPaint2 {

        static long _naptime = 10;

        public static void main(String[] args) {
          if (args.length > 0) {
            _naptime = Long.parseLong(args[0]);
          }

          JFrame frame = new JFrame("Heavyweight Canvas Paint Test");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(getContents());
          frame.setSize(500, 500);
          frame.setVisible(true);
        }

        public static Component getContents() {
          final MyJPanel leftPanel = new MyJPanel();
          leftPanel.setBorder(BorderFactory.createTitledBorder("Lightweight Panel"));
          leftPanel.setMinimumSize(new Dimension(240, 500));
          JPanel rightPanel = new JPanel();
          BoxLayout bl = new BoxLayout(rightPanel, BoxLayout.Y_AXIS);
          rightPanel.setLayout(bl);
          rightPanel.setBorder(BorderFactory.createTitledBorder("Heavyweight Panel"));
          final MyCanvas canvas = new MyCanvas();
          rightPanel.add(canvas);
          leftPanel.addMouseMotionListener(new MouseAdapter() {

            public void mouseMoved(MouseEvent e) {
              try {
                Thread.sleep(_naptime);
              } catch (InterruptedException ie) {
                ie.printStackTrace();
              }
              canvas.setXY(e.getX(), e.getY());
              System.out.println("Calling Canvas.repaint()");
              canvas.repaint();
              leftPanel.setXY(e.getX(), e.getY());
              System.out.println("Calling MyJPanel.repaint()");
              leftPanel.repaint();
              
            }
          });
          JSplitPane splitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
          splitter.setLeftComponent(leftPanel);
          splitter.setRightComponent(rightPanel);
          return splitter;
        }

        private static class MyJPanel extends JPanel {

          private int _x, _y;

          public void setXY(int x, int y) {
            _x = x;
            _y = y;
          }

          public void paint(Graphics g) {
            super.paint(g);
            System.out.println("MyJPanel.paint() called for x= " + _x + " y= " + _y);
            g.drawRect(_x, _y, 10, 10);
          }
        }

        private static class MyCanvas extends Canvas {

          private int _x, _y;

          public void setXY(int x, int y) {
            _x = x;
            _y = y;
          }

          public void paint(Graphics g) {
            System.out.println("MyCanvas.paint() called for x= " + _x + " y= " + _y);
            g.drawRect(_x, _y, 10, 10);
          }
        }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      Heavyweight component repainting results in a real PaintEvent (which is of lower priority), while Swing's repaint is implemented via InvokeLater (which is an InvocationEvent of a standard priority).

      Some possible workaround is to use the code like that:

        Graphics g = canvas.getGraphics();
        try {
          canvas.update(g); // or .paint() for incremental painting
        } finally {
          g.dispose();
        }

      instead of canvas.repaint() call. This synchronous painting is not a recommended way to go (and even deprecated for Swing components), but it may help in this particular case.

            vchoudhaorcl Vaibhav Choudhary (Inactive)
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: