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

Graphics corruption when scrolling right on JScrollPane with backing store

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      In my application I have a JScrollPane whose corresponding JViewport has `setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE)`, for speed.

      When scrolling to the right, the displayed image immediately and every time suffers graphical corruption, which takes the form of horizontal bands of misplaced pixels. The further or faster you scroll, the worse it gets, until the image is totally garbled. Scrolling left and scrolling vertically do not cause the problem.

      Although I'm reporting this against JScrollPane/JViewport, where I encountered the bug, I haven't found the real underlying cause. I have not managed to reproduce the bug on Windows, only on Linux, which suggests the real bug is located at a low level in some arcane buffer blitting function.


      ---------- BEGIN SOURCE ----------
      import java.awt.*;
      import java.awt.image.BufferedImage;
      import javax.swing.*;

      public class JViewportScrollingGlitch {
          public static void main(String[] args) {
              SwingUtilities.invokeLater(() -> {
                  BufferedImage image = getTestImage();
                  
                  JPanel imagePanel = new JPanel() {
                      @Override
                      public void paintComponent(Graphics g) {
                          g.drawImage(image, 0, 0, null);
                      }
                  };
                  imagePanel.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
                  
                  JScrollPane scrollPane = new JScrollPane(imagePanel);
                  scrollPane.setPreferredSize(new Dimension(600, 600));
                  
                  JViewport viewport = scrollPane.getViewport();
                  viewport.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE); // !!
                  
                  JFrame frame = new JFrame();
                  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                  frame.add(scrollPane);
                  frame.pack();
                  frame.setLocationRelativeTo(null);
                  frame.setVisible(true);
                  
                  if (false) {
                      // the glitch is also triggered programmatically, without using the scrollbar:
                      Timer timer = new Timer(500, actionEvent -> {
                          Point p = viewport.getViewPosition();
                          p.x += 25;
                          if (p.x >= viewport.getViewSize().width - viewport.getExtentSize().width) p.x = 0;
                          viewport.setViewPosition(p);
                      });
                      timer.setRepeats(true);
                      timer.start();
                  }
              });
          }
          
          private static BufferedImage getTestImage() {
              // toned gradient checkerboard
              final int imageSize = 2500;
              final int squareSize = 100;
              BufferedImage image = new BufferedImage(imageSize, imageSize, BufferedImage.TYPE_INT_RGB);
              Graphics2D g = image.createGraphics();
              g.setPaint(new LinearGradientPaint(
                  new Point(0, 0),
                  new Point(imageSize, 0),
                  new float[] { 0, 0.5f, 1 },
                  new Color[] { Color.red, Color.yellow, Color.blue }));
              g.fillRect(0, 0, imageSize, imageSize);
              g.setPaint(new LinearGradientPaint(
                  new Point(0, 0),
                  new Point(0, imageSize),
                  new float[] { 0, 1 },
                  new Color[] { Color.white, Color.darkGray }));
              for (int y = 0; y < imageSize; y += squareSize) {
                  for (int x = 0; x < imageSize; x += squareSize) {
                      if ((x + y) / squareSize % 2 != 0) {
                          g.fillRect(x, y, squareSize, squareSize);
                      }
                  }
              }
              g.dispose();
              return image;
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      If horizontal scrolling is needed, do not use JViewport.BACKINGSTORE_SCROLL_MODE. With the default BLIT_SCROLL_MODE, the glitch is not encountered. (There are potentially other graphical use cases affected by the same underlying bug, though.)

      FREQUENCY : always


            pardesha Pardeep Sharma
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: