JTextArea scroll to bottom only if text is appended

后端 未结 2 1992
不知归路
不知归路 2021-01-26 10:21

I am trying to create a JTextArea which scrolls to bottom every time a text is appended to that text area. Otherwise, the user should be able to scroll top and see

相关标签:
2条回答
  • 2021-01-26 11:10

    Check out Smart Scrolling.

    If the scrollbar is at the bottom, then as text is appended you will see the new text.

    If the user has scrolled to a different position, then the viewport will stay there until the user scrolls back to the bottom.

    0 讨论(0)
  • 2021-01-26 11:10

    As a simple (and rough) proof of concept...

    This basically adds a DocumentListener to the JTextArea and on any Document event, use setCaretPosition to move the caret to the end of the document.

    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Date;
    import java.util.WeakHashMap;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.Timer;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.event.DocumentEvent;
    import javax.swing.event.DocumentListener;
    import javax.swing.text.JTextComponent;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JTextArea ta = new JTextArea(10, 20);
                    ta.setWrapStyleWord(true);
                    ta.setLineWrap(true);
                    MoveToTheBottom.install(ta);
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new JScrollPane(ta));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                    Timer timer = new Timer(500, new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            ta.append(new Date().toString() + "\n");
                        }
                    });
                    timer.start();
                }
            });
        }
    
        public static class MoveToTheBottom implements DocumentListener {
    
            private static WeakHashMap<JTextComponent, DocumentListener> registry = new WeakHashMap<>(25);
            private JTextComponent parent;
    
            protected MoveToTheBottom(JTextComponent parent) {
                this.parent = parent;
                parent.getDocument().addDocumentListener(this);
            }
    
            public static void install(JTextComponent parent) { 
                MoveToTheBottom bottom = new MoveToTheBottom(parent);
                registry.put(parent, bottom);
            }
    
            public static void uninstall(JTextComponent parent) {
                DocumentListener listener = registry.remove(parent);
                if (listener != null) {
                    parent.getDocument().removeDocumentListener(listener);
                }
            }
    
            @Override
            public void insertUpdate(DocumentEvent e) {
                parent.setCaretPosition(e.getDocument().getLength());
            }
    
            @Override
            public void removeUpdate(DocumentEvent e) {
                parent.setCaretPosition(e.getDocument().getLength());
            }
    
            @Override
            public void changedUpdate(DocumentEvent e) {
                parent.setCaretPosition(e.getDocument().getLength());
            }
    
        }
    
    }
    

    The example demonstrates a possible re-usable API which you can use to "install" and "uninstall" the support as reqiured

    0 讨论(0)
提交回复
热议问题