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

Scrolling in default BLIT_SCROLL_MODE painting JTextArea components hangs all

XMLWordPrintable

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

      ADDITIONAL OS VERSION INFORMATION :
      Windows XP
      Version: 5.1.2600
      Service Pack: 2.0
      Hot Fix: KB903235


      A DESCRIPTION OF THE PROBLEM :
      When drawing JComponent Text Areas and dynamically scrolling, Java gets confused, gets the shivers and freezes when the viewport cannot get its arms around the canvas.
      Possible problem at JViewport.scrollRectToVisible().

      When painting non-text area components eg. graphics circles, it is ok.

      Have provided example code. This code is based on the ScrollDemo2 example provided in the Sun Java Tutorial

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Usage: run program and repeatedly click the left mouse button near right boundary to create a new JComponent node each time and to force scrolling area to increase in size to the right.
      When the first node crosses the left boundary, then the scroll pane gets confused, gets the shivers and hangs.
      The other scroll modes are a bit better - but very slow leaving the toolbar (in the oroginal application) unpainted sometimes.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      scroll normally.
      ACTUAL -
      When the first node crosses the left boundary, then the scroll pane gets confused, gets the shivers and hangs.


      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      /*
       * to show possible bug when in the default BLIT_SCROLL_MODE and with JTextArea components.
       * author: Anil Philip. juwo LLC. http://juwo.com
       * Usage: run program and repeatedly click the left mouse button near right boundary to
       * create a new JComponent node each time and to force scrolling area to increase in size to the right.
       * When the first node crosses the left boundary, then the scroll pane gets confused, gets the shivers and hangs.
       * The other scroll modes are a bit better - but very slow leaving the toolbar (in the oroginal application)
       * unpainted sometimes.
       *
       * This code is based on the ScrollDemo2 example provided in the Sun Java Tutorial (written by John Vella, a tutorial reader).
       */

      import javax.swing.*;
      import javax.swing.border.EtchedBorder;
      import java.awt.*;
      import java.awt.event.*;
      import java.util.*;

      /* ScrollDemo2WithBug.java is a 1.5 application that requires no other files. */
      public class ScrollDemo2WithBug extends JPanel {
          private Dimension area; //indicates area taken up by graphics

          private Vector circles; //coordinates used to draw graphics

          private Vector components;

          private JPanel drawingPane;

          public ScrollDemo2WithBug() {
              super(new BorderLayout());

              area = new Dimension(0, 0);
              circles = new Vector();
              components = new Vector();

              //Set up the instructions.
              JLabel instructionsLeft = new JLabel(
                      "Click left mouse button to place a circle.");
              JLabel instructionsRight = new JLabel(
                      "Click right mouse button to clear drawing area.");
              JPanel instructionPanel = new JPanel(new GridLayout(0, 1));
              instructionPanel.add(instructionsLeft);
              instructionPanel.add(instructionsRight);

              //Set up the drawing area.
              drawingPane = new DrawingPane();
              drawingPane.setBackground(Color.white);

              drawingPane.setPreferredSize(new Dimension(200, 200));

              //Put the drawing area in a scroll pane.
              JScrollPane scroller = new JScrollPane(drawingPane);
        // scroller.getViewport().setScrollMode(JViewport.SIMPLE_SCROLL_MODE);
              if(scroller.getViewport().getScrollMode() == JViewport.BACKINGSTORE_SCROLL_MODE)
                  System.out.println("BACKINGSTORE_SCROLL_MODE");
              if(scroller.getViewport().getScrollMode() == JViewport.BLIT_SCROLL_MODE)
                  System.out.println("BLIT_SCROLL_MODE");
              if(scroller.getViewport().getScrollMode() == JViewport.SIMPLE_SCROLL_MODE)
                  System.out.println("SIMPLE_SCROLL_MODE");
             
              //Lay out this demo.
              add(instructionPanel, BorderLayout.PAGE_START);
              add(scroller, BorderLayout.CENTER);
          }

          /** The component inside the scroll pane. */
          public class DrawingPane extends JPanel implements MouseListener {
              private class VisualNode {
                  int x = 0;

                  int y = 0;

                  int id = 0;

                  public VisualNode(int id, int x, int y) {
                      this.id = id;
                      this.x = x;
                      this.y = y;
                      title.setLineWrap(true);
                      title.setAlignmentY(Component.TOP_ALIGNMENT);
                      titlePanel.add(new JButton("Hi!"));
                      titlePanel.add(title);
                      nodePanel.add(titlePanel);
                      nodePanel.setBorder(BorderFactory
                              .createEtchedBorder(EtchedBorder.RAISED));
                      box.add(nodePanel);
                      ScrollDemo2WithBug.this.drawingPane.add(box);
                  }
                  Box box = Box.createVerticalBox();
                  Box titlePanel = Box.createHorizontalBox();
                  JTextArea title = new JTextArea(1, 10); // 1 rows x 10 cols
                  Box nodePanel = Box.createVerticalBox();

                  public void paintNode(Graphics g) {
                      int ix = (int) x + ScrollDemo2WithBug.this.getInsets().left;
                      int iy = (int) y + ScrollDemo2WithBug.this.getInsets().top;
                      title.setText(id + " (" + ix + "," + iy + ") ");
                      box.setBounds(ix, iy, box.getPreferredSize().width, box
                              .getPreferredSize().height);
                  }
              }

              int n = 0;

              DrawingPane() {
                  this.setLayout(null);
                  addMouseListener(this);
                  
              }

              protected void paintComponent(Graphics g) {
                  super.paintComponent(g);
                  g.fill3DRect(10, 10, 25, 25, true);
                  Point point;
                  for (int i = 0; i < circles.size(); i++) {
                      point = (Point) circles.elementAt(i);
                      VisualNode node = (VisualNode) components.get(i);
                      node.paintNode(g);

                  }
              }

              //Handle mouse events.
              public void mouseReleased(MouseEvent e) {
                  final int W = 100;
                  final int H = 100;
                  boolean changed = false;
                  if (SwingUtilities.isRightMouseButton(e)) {
                      //This will clear the graphic objects.
                      circles.removeAllElements();
                      area.width = 0;
                      area.height = 0;
                      changed = true;
                  } else {
                      int x = e.getX() - W / 2;
                      int y = e.getY() - H / 2;
                      if (x < 0)
                          x = 0;
                      if (y < 0)
                          y = 0;
                      Point point = new Point(x, y);
                      VisualNode node = new VisualNode(circles.size(), point.x,
                              point.y);
                      // add(node);
                      components.add(node);
                      circles.addElement(point);
                      drawingPane.scrollRectToVisible(new Rectangle(x, y, W, H));

                      int this_width = (x + W + 2);
                      if (this_width > area.width) {
                          area.width = this_width;
                          changed = true;
                      }

                      int this_height = (y + H + 2);
                      if (this_height > area.height) {
                          area.height = this_height;
                          changed = true;
                      }
                  }
                  if (changed) {
                      //Update client's preferred size because
                      //the area taken up by the graphics has
                      //gotten larger or smaller (if cleared).
                      drawingPane.setPreferredSize(area);

                      //Let the scroll pane know to update itself
                      //and its scrollbars.
                      drawingPane.revalidate();
                  }
                  drawingPane.repaint();
              }

              public void mouseClicked(MouseEvent e) {
              }

              public void mouseEntered(MouseEvent e) {
              }

              public void mouseExited(MouseEvent e) {
              }

              public void mousePressed(MouseEvent e) {
              }
          }

          /**
           * Create the GUI and show it. For thread safety, this method should be
           * invoked from the event-dispatching thread.
           */
          private static void createAndShowGUI() {
              //Make sure we have nice window decorations.
              JFrame.setDefaultLookAndFeelDecorated(true);

              //Create and set up the window.
              JFrame frame = new JFrame("ScrollDemo2");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

              //Create and set up the content pane.
              JComponent newContentPane = new ScrollDemo2WithBug();
              newContentPane.setOpaque(true); //content panes must be opaque
              frame.setContentPane(newContentPane);

              //Display the window.
              frame.setSize(800, 600);
              frame.pack();
              frame.setVisible(true);
          }

          public static void main(String[] args) {
              //Schedule a job for the event-dispatching thread:
              //creating and showing this application's GUI.
              javax.swing.SwingUtilities.invokeLater(new Runnable() {
                  public void run() {
                      createAndShowGUI();
                  }
              });
          }
      }

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

            Unassigned Unassigned
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: