Gotler
Gotler

Reputation: 3

Dynamic JTextArea in JScrollPane ends up under scroll bar

I have a JFrame with a JScrollPane containing a JTextArea. The scrollpane is configured to never show the horizontal scrollbar, and show the vertical scrollbar as needed. As the text in the text area grows the vertical scrollbar eventually appears, hiding part of the text area. I would expect the scrollbar to resize its content as needed when the scrollbar appears.

One workaround I've found is to always display the vertical scrollbar, but that doesn't look good, as it's rarely needed.

The below code snippet reproduces the problem after enough text is entered on my system (Windows 10)

import javax.swing.*;
import java.awt.*;
import static javax.swing.ScrollPaneConstants.*;

public class Test {
    public static void main(String[] args) {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.add(new JLabel("text"));
        panel.add(new JLabel("text"));
        panel.add(new JLabel("text"));

        JTextArea textArea = new JTextArea();
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        textArea.setText("This text fits");
        panel.add(textArea);

        JScrollPane scrollPane =
                new JScrollPane(panel, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_NEVER);

        JFrame frame = new JFrame("Title");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().add(scrollPane);

        frame.pack();
        frame.setVisible(true);
    }
}

Upvotes: 0

Views: 1799

Answers (4)

Aman
Aman

Reputation: 787

Just a problem with component's placement. Refer below code:

public TestFrame() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    setContentPane(contentPane);
    contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));

    JScrollPane scrollPane = new JScrollPane();
    contentPane.add(scrollPane);

    JPanel panel = new JPanel();
    scrollPane.setColumnHeaderView(panel);
    panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

    JLabel lblNewLabel = new JLabel("text");
    panel.add(lblNewLabel);

    JLabel lblNewLabel_2 = new JLabel("text");
    panel.add(lblNewLabel_2);

    JLabel lblNewLabel_1 = new JLabel("text");
    panel.add(lblNewLabel_1);

    JTextArea textArea = new JTextArea();
    textArea.setLineWrap(true);
    textArea.setText("This text fits");
    scrollPane.setViewportView(textArea);
}

Hope this will help. :-)

Upvotes: 0

camickr
camickr

Reputation: 324118

Playing with not showing the horizontal scrollbar doesn't really help.

Instead you need to implement the Scrollable interface to tell the scrollpane that the panel should always be fit into the width of the scrollpane. This will cause the text in the text area to be wrapped properly as text is added.

Instead of implementing the Scrollable interface you can use the Scrollable Panel, which allows you to change the scrollable properties using methods of the class.

You just need to change your code as follow:

//JPanel panel = new JPanel();
ScrollablePanel panel = new ScrollablePanel();
panel.setScrollableWidth( ScrollablePanel.ScrollableSizeHint.FIT );

Upvotes: 0

Antony Ng
Antony Ng

Reputation: 797

Override doLayout() and do anything you want, at doLayout(), you have final say to what to do with your child components (after the work of layout manager has finished).

But you need to make the textArea and scrollPane become attributes first, because you need to reference them later:

private static JTextArea textArea;
private static JScrollPane scrollPane;

public static void main(String[] args) {
    JPanel panel = new JPanel() {
        @Override
        public void doLayout() {
            super.doLayout();

            if (scrollPane.getVerticalScrollBar().isVisible()) {
                textArea.setSize(textArea.getWidth() - 3, textArea.getHeight());
            }
        }
    };

Upvotes: -1

Andrew Thompson
Andrew Thompson

Reputation: 168825

To fix the problem, change:

JTextArea textArea = new JTextArea();

To:

JTextArea textArea = new JTextArea(1,20);

By providing size hints to the text area, the scroll pane is better able to deal with it when more text is added.

Upvotes: 2

Related Questions