JDK-4834399 : invokeLater causes JScrollPane to scroll to bottom at creation
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.1
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2003-03-19
  • Updated: 2003-08-27
  • Resolved: 2003-08-27
Related Reports
Duplicate :  
Relates :  
Relates :  
Description

Name: jk109818			Date: 03/18/2003


FULL PRODUCT VERSION :
See System Info

Version = Sun ONE Studio 4u1 CE

EXTRA RELEVANT SYSTEM CONFIGURATION :
Product version SUN ONE Studio 4 update 1,
CE, Build 020923
IDE versioning IDE/1 spec=1.43.3.1 impl =
020923
OS Windows 2000 version 5.0 running on x86
Java 1.4.1
VM Java HotSpot Client VM 1.4.1-b21
System Locale: en_GB (f4j_ce)


A DESCRIPTION OF THE PROBLEM :
I have a problem that seems to be an invokeLater
bug. My intention is to have a simple dialog with
a scrollable textarea, where the scrollbar is at
the top when the dialog is opened. Because I
want a non-blocking modal dialog I am trying to
show the dialog using SwingUtilities.invokeLater.
The problem is, for some reason this causes the
scrollbar to start at the bottom of the textarea; if I
show the dialog without using invokeLater, the
scrollbar does start at the top. I have isolated
this behavior in the attached program code.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Execute the attached program with "if (true)"
in the main to experience the expected behavior
2. Execute the attached program with "if (false)"
in the main to experience the actual faulty
behavior

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected: scrollbar at the top
Actual: scrollbar at the bottom

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * MessageDialog2.java
 *
 * Created on 16 December 2002, 16:22
 */

import java.awt.Frame;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

/**
 *
 * @author  smakmanc
 */
public class MessageDialog2 extends JDialog {
    
    /** Creates new form MessageDialog2 */
    public MessageDialog2() {
        super(new JFrame(), true);
        initComponents();
        detailsTextArea.setText
("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nn\n");
    }
    
    /** This method is called from within the
constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The
content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {
        java.awt.GridBagConstraints
gridBagConstraints;

        mainPanel = new javax.swing.JPanel();
        messagePanel = new javax.swing.JPanel();
        detailsScrollPane = new
javax.swing.JScrollPane();
        detailsTextArea = new
javax.swing.JTextArea();

        addWindowListener(new
java.awt.event.WindowAdapter() {
            public void windowClosing
(java.awt.event.WindowEvent evt) {
                closeDialog(evt);
            }
        });

        mainPanel.setLayout(new
java.awt.BorderLayout());

        messagePanel.setLayout(new
java.awt.GridBagLayout());

        detailsScrollPane.setMaximumSize(new
java.awt.Dimension(80, 80));
        detailsScrollPane.setMinimumSize(new
java.awt.Dimension(0, 16));
        detailsScrollPane.setPreferredSize(new
java.awt.Dimension(80, 80));
        detailsScrollPane.setViewportView
(detailsTextArea);

        gridBagConstraints = new
java.awt.GridBagConstraints();
        gridBagConstraints.fill =
java.awt.GridBagConstraints.BOTH;
        messagePanel.add(detailsScrollPane,
gridBagConstraints);

        mainPanel.add(messagePanel,
java.awt.BorderLayout.CENTER);

        getContentPane().add(mainPanel,
java.awt.BorderLayout.CENTER);

        pack();
    }
    
    /** Closes the dialog */
    private void closeDialog
(java.awt.event.WindowEvent evt) {
        setVisible(false);
        dispose();
    }
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        if (false) {
            new MessageDialog2().show();
        }
        else {
            SwingUtilities.invokeLater(new Runnable
() {
                public void run() {
                    new MessageDialog2().show();
                    System.exit(0);
                }
            });
        }
    }
    
    // Variables declaration - do not modify
    private javax.swing.JPanel messagePanel;
    private javax.swing.JTextArea detailsTextArea;
    private javax.swing.JScrollPane
detailsScrollPane;
    private javax.swing.JPanel mainPanel;
    // End of variables declaration
    
}

---------- END SOURCE ----------
(Review ID: 179166) 
======================================================================

Comments
EVALUATION Name: anR10225 Date: 03/21/2003 The reason of such behavior is javax.swing.text.DefaultCaret.async property. When JTextArea.setText() is invoked in DispatchThread the caret updates its position due to DefaultCaret.UpdateHandler.insertUpdate() and the text area scrolls to bottom. But when the setText() is invoked from other thread the condition if (async || SwingUtilities.isEventDispatchThread()) (in DefaultCaret.UpdateHandler.insertUpdate() method) fails, the caret doesn't updates its position and thus remains on its initial position (0). Think the 'async' property should be removed from DefaultCaret since JTextComponent.setText() method is declared as 'thread safe'. There should be another mechanism to enable/disable caret position updates. ====================================================================== Name: anR10225 Date: 08/27/2003 Currently the new 'updatePolicy' property is added to the DefaultCaret class (see the bug #4201999). It may control the behavior of the caret (and therefore text component scrolling) when the document mutates. The default caret behavior remains the same because of compatibility reasons, but you may change it by setting the 'updatePolicy' property. In the test case submitted you may position the caret of the text area to the beginning of the text : detailsTextArea.setText("\n\n\n\n\n\n\n\n\n\n\n\n\n\"); detailsTextArea.setCaretPosition(0); or turn off caret updates ((DefaultCaret)detailsTextArea.getCaret()).setUpdatePolicy (DefaultCaret.NEVER_UPDATE); detailsTextArea.setText("\n\n\n\n\n\n\n\n\n\n\n\n\n\"); to avoid text area to scroll to the last line. Close this bug as duplicate. ======================================================================
11-06-2004