Search code examples
javaswingjscrollpanejtextarea

Writing at the bottom of JTextArea


I have a JScrollPane and a JTextArea (editable) with 10 rows. I want the first user input to appear at the bottom of the JTextArea and the most recent input should push the previous input upward. To achieve this I use textArea.setMargin(new Insets(x,0,0,0)); and everything works as it should - except that my second input will toggle the JScrollPane.

How can I start at the bottom of the JTextArea and only enable scrolling when the entire original viewport is filled?

enter image description here


Solution

  • Basically, you could add the JTextText onto a JPanel with another JPanel which acts a filler, causing the JTextArea to occupy the smallest space it actually needs.

    I did this by using GridBagLayout to force the fill to occupy the most of space it could...

    Scrolling

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class TestTextArea {
    
        public static void main(String[] args) {
            new TestTextArea();
        }
    
        public TestTextArea() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new JScrollPane(new TestPane()));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private JTextArea ta;
    
            public TestPane() {
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = 0;
                gbc.gridy = 0;
                gbc.weightx = 1;
                gbc.weighty = 1;
                gbc.fill = GridBagConstraints.BOTH;
    
                JPanel filler = new JPanel();
                filler.setBackground(Color.WHITE);
                add(filler, gbc);
    
                gbc.gridy = 1;
                gbc.weighty = 0;
                ta = new JTextArea(1, 20);
                add(ta, gbc);
            }
        }
    
    }