JTextArea на JPanel внутри JScrollPane неправильно изменяет размер

Я хотел бы добиться следующего:

+------------------Other container(s)-----------------+
|        +------JScrollPane (vertical)-------+        |
|        | JTextField                        |        |
|        | Box.createRigidArea (vertical)    |        | 
|        | JTextArea                         |        |
|        | { etc.. any other J-component }   |        |
|        |                                   |        |
|        |                                   |        |
|        |                                   |        |
|        |                                   |        |
|        +-----------------------------------+        |
+-----------------------------------------------------+

Самое близкое, что я могу получить, это следующий (псевдо) код:

JPanel container = new JPanel(new BorderLayout());
JPanel innerContainer = new JPanel();
innerContainer.setLayout(new BoxLayout(_innerContainer, BoxLayout.Y_AXIS));
JScrollPane scrollPane = new JScrollPane(innerContainer);
container.add(scrollPane, BorderLayout.NORTH);

Всякий раз, когда я хотел бы добавить компоненты, они добавляются во внутренний контейнер:

innerContainer.add(new JTextField());
innerContainer.add(Box.createRigidArea(new Dimension(0, 10)));
innerContainer.add(new JTextArea());
innerContainer.add(Box.createRigidArea(new Dimension(0, 10)));
innerContainer.add(new JLabel());

.... так далее

Я сталкиваюсь со следующими проблемами:

Я позволил менеджерам компоновки позаботиться обо всех размерах элементов пользовательского интерфейса. Поэтому предпочтительно, чтобы я не использовал какой-либо метод.setxxSize(). JTextArea, занятая большим количеством текста, будет использовать все необходимое пространство (вертикальное и горизонтальное). Что совершенно нормально. Всякий раз, когда размер кадра изменяется, JTextArea будет расти, что все еще в полном порядке. Но всякий раз, когда я сжимаю рамку, JTextArea не корректируется соответственно. Поэтому появляется горизонтальная полоса прокрутки, но этого я бы хотел избежать. Я хочу, чтобы пользователи только прокручивали по вертикали.

У кого-нибудь есть хорошие советы? Спасибо!

РЕДАКТИРОВАТЬ:

SSCCE:

import java.awt.*;

import javax.swing.*;

public class VerticalStackPanel extends JFrame {

    public static void main(String[] args) {
        JFrame frame = new VerticalStackPanel();
        frame.setSize(800, 600);
        frame.setVisible(true);
    }

    public VerticalStackPanel() {
        super();

        JScrollPane scrollPane = new JScrollPane(createVerticalStackPanel());
        scrollPane.getVerticalScrollBar().setUnitIncrement(16);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

        getContentPane().add(scrollPane);
    }

    private Component createVerticalStackPanel() {
        JPanel container = new JPanel(new BorderLayout());
        container.add(createInnerContainer(), BorderLayout.NORTH);

        return container;
    }

    private Component createInnerContainer() {
        JPanel innerContainer = new JPanel();
        innerContainer.setLayout(new BoxLayout(innerContainer, BoxLayout.Y_AXIS));

        innerContainer.add(createTextArea());
        innerContainer.add(Box.createRigidArea(new Dimension(0, 10)));
        innerContainer.add(createTextArea());
        innerContainer.add(Box.createRigidArea(new Dimension(0, 10)));
        innerContainer.add(createTextArea());
        innerContainer.add(Box.createRigidArea(new Dimension(0, 10)));
        innerContainer.add(createTextArea());
        innerContainer.add(Box.createRigidArea(new Dimension(0, 10)));
        innerContainer.add(createTextArea());
        innerContainer.add(Box.createRigidArea(new Dimension(0, 10)));
        innerContainer.add(createTextArea());
        innerContainer.add(Box.createRigidArea(new Dimension(0, 10)));

        return innerContainer;
    }

    private Component createTextArea() {
        JTextArea textArea = new JTextArea();
        textArea.setText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vitae diam nunc. Proin vulputate, odio consectetur tincidunt aliquet, metus ipsum rhoncus tellus, in dignissim ligula tortor at risus. Aenean rhoncus lorem a magna luctus molestie. Fusce consequat enim vel quam pharetra varius. Vivamus porta condimentum orci non ultrices. Duis magna arcu, fringilla ut eleifend a, volutpat ac elit. Sed ligula enim, dictum id fringilla vitae, ornare vel nulla. Proin lobortis suscipit lectus eget placerat. Morbi aliquam dolor quis lectus tincidunt eu volutpat risus fermentum. Nunc et sapien a nisl aliquet auctor. Phasellus nec sem tellus, et scelerisque sapien. In a nibh vestibulum velit convallis sodales. Vestibulum tempor fringilla vulputate. Duis hendrerit dolor id urna aliquam cursus auctor enim pulvinar. Nulla rutrum fringilla eros, id congue nisi mattis in. Pellentesque consectetur eleifend mauris, ut aliquam purus convallis ac. Vestibulum pretium, sem at congue faucibus, leo leo volutpat odio, ut feugiat nulla felis a diam. Praesent dignissim eros ac eros semper auctor. Phasellus eu sapien nibh. Quisque pulvinar tristique lectus, quis porttitor purus suscipit sed. Curabitur gravida, ipsum ut vehicula aliquet, erat ipsum tincidunt nulla, eget bibendum felis dolor vel risus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus vitae nisl odio, blandit laoreet nibh.");
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        return textArea;
    }

}

Всякий раз, когда вы будете изменять размер фрейма по горизонтали, текст будет исчезать всякий раз, когда фрейм станет меньше. Появляется горизонтальная полоса прокрутки, но с тех пор:

scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

Текст просто исчезает... JTextArea должен настроить соответственно

4 ответа

Решение

Итак, проблема в том, что JPanel не любит встраиваться в JScrollPane.

Для того, чтобы компонент "хорошо играл" с JScrollPane, он должен реализовать Scrollable. Если вы просто добавили JTextArea в JScrollPane, он будет работать именно так, как вам нужно.

Вместо использования JPanel для хранения всех ваших JTextAreas вам нужно создать небольшой пользовательский класс, расширяющий JPanel и реализующий Scrollable.

Я переписал ваш пример и вставил его здесь: http://pastebin.com/q9x4fv3H чтобы вы могли увидеть весь код. Прокручиваемый JPanel должен выглядеть следующим образом:

private static class ScrollablePanel extends JPanel implements Scrollable{
    public Dimension getPreferredScrollableViewportSize() {
        return super.getPreferredSize(); //tell the JScrollPane that we want to be our 'preferredSize' - but later, we'll say that vertically, it should scroll.
    }

    public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
        return 16;//set to 16 because that's what you had in your code.
    }

    public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
        return 16;//set to 16 because that's what you had set in your code.
    }

    public boolean getScrollableTracksViewportWidth() {
        return true;//track the width, and re-size as needed.
    }

    public boolean getScrollableTracksViewportHeight() {
        return false; //we don't want to track the height, because we want to scroll vertically.
    }
}

Ура!

Вы должны добавить видовой экран для вашего scrollPane:

scrollPane.setViewportView(textArea)

JTextArea никогда не сжимается, когда включен перенос строки

У меня есть JTextArea в JPanel с Gridlayout, которая имеет эту проблему. Моя проблема была решена простой установкой минимального размера TextArea.

textArea.setMinimumSize(new Dimension(20,40));

Использование

txtArea.setWrapStyleWord(true);
txtArea.setLineWrap(true);

Он переносит текст и избегает горизонтальной полосы прокрутки.

И попробуйте GridBagLayout. Используйте вес и вес. Это позаботится о проблемах изменения размера

Другие вопросы по тегам