1

I noticed some interesting behavior with JScrollPane when manipulating the underlying document in a JTextPane. Consider this example:

public class Example {

    public static void main(String[] args) {
        String text = "I like trains :)\n";
        createExample(1, doc -> doc.insertString(doc.getLength(), text, null));
        createExample(2, doc -> doc.insertString(doc.getEndPosition().getOffset(), text, null));
    }

    private static void createExample(int exampleNumber, ThrowingConsumer<Document> insertAction) {
        JTextPane textPane = new JTextPane();
        JScrollPane scrollPane = new JScrollPane(textPane);
        
        Document document = textPane.getDocument();
        JButton insert = new JButton("Insert" + exampleNumber);
        insert.addActionListener(e -> {
            try {
                insertAction.accept(document);
            } catch (Throwable e1) {
                e1.printStackTrace();
            }
        });

        JFrame frame = new JFrame("Test Frame " + exampleNumber);
        frame.setLayout(new BorderLayout(0, 10));
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.add(insert, BorderLayout.SOUTH);

        frame.setSize(400, 200);
        frame.setLocationByPlatform(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    private static interface ThrowingConsumer<T> {
        void accept(T t) throws Throwable;
    }

}

This creates two frames that append text to a text pane's underlying document when a button is pushed. The frames have almost identical logic, with the only distinction being that the first frame uses Document.getLength() when inserting the text and the second frame uses Document.getEndPosition() and Position.getOffset().

Somehow, the first frame will automatically scroll to the bottom when the text is appended, while the second frame will remain at the start of the document (unless the user drags the scrollbar manually).

Does anyone know why this is?

4
  • 1
    When I click on Insert2 [JButton], I get an error: javax.swing.text.BadLocationException: Invalid insert
    – Abra
    Commented Oct 20, 2023 at 19:10
  • @Abra strange. That is not happening for me. I am using JDK 8. Commented Oct 20, 2023 at 19:25
  • It seems doc.getEndPosition().getOffset() returns 1 in all versions of Java. And doc.getText(0, doc.getEndPosition().getOffset()) returns "\u000a" in all versions of Java. I suspect there’s a “magic” Element at the end, which was mistakenly treated as normal text in Java 8.
    – VGR
    Commented Oct 20, 2023 at 19:42
  • the first frame will automatically scroll to the bottom when the text is appended, - check out Text Area Scrolling for what I believe to be the conditions for automatic scrolling. I also get a BLE on the second frame (JDK 11). The BLE is on the getEndPosition(...) method which tells me there is something in the logic that changes the state of the Document to break one of the conditions for automatic scrolling.
    – camickr
    Commented Oct 20, 2023 at 20:50

0