JDK-6331073 : JScrollPane repaints incorrectly on larger monitor of dual monitor system
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0
  • Priority: P5
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2005-09-30
  • Updated: 2011-02-16
  • Resolved: 2005-10-05
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_03-b07)
Java HotSpot(TM) Client VM (build 1.5.0_03-b07, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]


EXTRA RELEVANT SYSTEM CONFIGURATION :
Two categories here:

1) Details that are probably important

2) Details that probably don't matter.

A DESCRIPTION OF THE PROBLEM :
In a two monitor configuration, when an application is in the larger window,
the JScrollPane will not completely repaint the screen on scrolling. The top
two-thirds or so of the screen repaint properly, but the bottom third doesn't
change.
This happens on a laptop when the external monitor has a significantly higher
resolution than the laptop.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test program. Each line is numbered on the left side, from 0 to 999. The window will probably open Create a hardware configuration as described above. (Laptop? dual monitor, #2
moniter larger than monitor 1 by at least 15%.
Launch the test app. The frame will probably open in the smaller screen.
Drag the frame to the larger screen.
It will be scrolled to the beginning. Click one of the buttons at the top,
(not the first one). JScroll pane will jump to the character number in the button
Look at the numbers to see if they are consecutive.
The diagonal text ribbon on the right resets itself every 60 lines, but it
can usually be used to spot the discontinueity.
Then, for extra credit, try dragging the scroll bar up and down.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The numbers on the left should always remain consecutive. This means the screen redrew every line properly.
ACTUAL -
The numbers on the left will abruptly change near the bottom of the screen. Usually they will be the image that was on the screen prior to the scroll. Again, it behaves properly on the small screen.

REPRODUCIBILITY :
This bug can be reproduced always.

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

public class TextScrollBug extends JPanel {
    private JTextArea pane;

    public static void main(String[] args) {
        JFrame mf = new JFrame("TextScrollBug");
        mf.setBounds(10, 10, 400, 300);
        mf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mf.add(new TextScrollBug());
        mf.setVisible(true);
        System.out.println("count" + mf.getContentPane().getComponentCount());
    }

    public TextScrollBug() {
        super(new BorderLayout());
        pane = new JTextArea();
        JScrollPane scr = new JScrollPane(pane);
        String text = " abcdefg hijklmnop qrstuv wxyz ABCDEFG HIJKLMNOP QRSTUV WXYZ";
        StringBuilder bldr = new StringBuilder();
        int sLen = text.length();
        for (int ii=0; ii<1000; ++ii)
        {
            bldr.append(ii);
            bldr.append("   ");
            int limit = ii % sLen;
            for (int jj=0; jj<limit; ++jj)
                bldr.append(" ");
            bldr.append(text);
            bldr.append('\n');
        }
        pane.setText(bldr.toString());
        add(scr, BorderLayout.CENTER);

        ActionListener al = new ActionListener()
        {
            public void actionPerformed(ActionEvent e) {
                String cmd = e.getActionCommand();
                int iCmd = Integer.parseInt(cmd);
                pane.select(iCmd, iCmd);
            }
        };
        JPanel buttons = new JPanel(new GridLayout());
        int max = bldr.length();
        for (int ii=0; ii<10; ++ii)
        {
            JButton btn = new JButton("" + ((ii*max)/10));
            buttons.add(btn);
            btn.addActionListener(al);
        }
        add(buttons, BorderLayout.NORTH);
    }
}

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

Comments
WORK AROUND Override RepaintManager's getDoubleBufferMaximumSize to return a bigger size. Here's what the new code does: Rectangle virtualBounds = new Rectangle(); GraphicsEnvironment ge = GraphicsEnvironment. getLocalGraphicsEnvironment(); for (GraphicsDevice gd : ge.getScreenDevices()) { GraphicsConfiguration gc = gd.getDefaultConfiguration(); virtualBounds = virtualBounds.union(gc.getBounds()); } doubleBufferMaxSize = new Dimension(virtualBounds.width, virtualBounds.height);
05-10-2005

EVALUATION Previously the RepaintManager would constrain the size of the offscreen image to the size of the primary screen. JViewport, when it blits, wasn't making sure the image was big enough, so that it was possible for only part of the component to be drawn. 5086872 fixed this by adding the logic to make sure the offscreen image is as big as all the screens. Closing as a duplicate.
05-10-2005