0
votes

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);
    }
}
4
I would expect the scrollbar to resize its content as needed when the scrollbar appears. - that is not what a scrollpane does. As the size of the components added to the scrollpane increase the scrollbar appears. Therefore you can then use the scrollbar to scroll the components up/down in the scrollpane to see all the components. I suspect that you really only want the scrollbar on the text area to that all the components are visible and then text in the text area scrolls as you add more text. - camickr

4 Answers

2
votes

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.

0
votes

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 );
0
votes

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. :-)

-1
votes

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());
            }
        }
    };