9

I'd like to achieve the following:

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

The closest I'm able to get is with the following (pseudo) code:

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

Whenever I'd like to add components they're added to the inner container:

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

.... etc

I'm facing the following problems:

I let the layout managers take care of all UI element size. So preferable I do not use any .setxxSize()-method. A JTextArea, occupied with alot of text, will use all the required space (vertical and horizontal). Which is totally fine. Whenever the frame is resized the JTextArea will grow, which is still totally fine. But whenever I shrink the frame, the JTextArea does not adjust accordingly. Therefore a horizontal scrollbar appears, but this I'd like to avoid. I want users only to scroll vertically.

Does anyone have some good tips? Thanks!

EDIT:

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

}

Whenever you'll resize the frame horizontally, text will dissapear whenever the frame becomes less big. A horizontal scrollbar appears, but since:

scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

Text just dissapears.. the JTextArea should adjust accordingly

Kylar
  • 8,876
  • 8
  • 41
  • 75
Velth
  • 1,108
  • 3
  • 15
  • 29
  • 1
    Can you please post an [SSCCE](http://sscce.org/) – joey rohan Apr 03 '13 at 09:07
  • @kleopatra uhh, you're correct. There is no relation to swingx, removing the tag as we speak. SSCCE link: https://gist.github.com/anonymous/5299682 – Velth Apr 03 '13 at 09:45
  • @kleopatra misunderstood your comment, fixed! – Velth Apr 03 '13 at 10:47
  • darn, you got me wondering and doubting and hair-pulling ... until I detected the "outer panel" (which you mentioned, silly me simply didnt see it ;-) FYI, if by any chance you are using swingx: JXPanel already implements Scrollable and comes with configurable size-tracking strategies – kleopatra Apr 03 '13 at 12:58

4 Answers4

20

Ok, so the issue is that JPanel does not like to be embedded into a JScrollPane.

In order for a component to "Play Nicely" with JScrollPane, it needs to implement Scrollable. If you just added a JTextArea into the JScrollPane, it would work exactly as you desired.

Instead of using a JPanel to hold all your JTextAreas, you'll need to make a small custom class that extends JPanel and implements Scrollable.

I've re-written your example and pasted it here: http://pastebin.com/q9x4fv3H so that you can see all the code. The Scrollable JPanel should look like this:

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.
    }
}

Cheers!

Kylar
  • 8,876
  • 8
  • 41
  • 75
  • 3
    You're the hero of today! Thanks for the clear explanation, works perfectly! – Velth Apr 03 '13 at 12:22
  • was about to upvote - until I saw the textArea.setMinimumSize ;-) Simply [don't fiddle with sizing hints](http://stackoverflow.com/a/7229519/203657), ever. – kleopatra Apr 03 '13 at 12:52
  • @kleopatra it actually works perfectly without the setMinimumSize too : ) – Velth Apr 03 '13 at 13:07
  • @MarkvanVelthoven yeah, I know - it's just me pressurizing everybody to remove all setXXSize from all answers :-) – kleopatra Apr 03 '13 at 13:10
  • Yeah that's actually from when I was fiddling around, forgot to remove it. – Kylar Apr 03 '13 at 13:46
  • Glad it worked for more than 1 person. It's been a loooong time (~7 years) since I've done Swing. – Kylar Apr 03 '13 at 14:03
  • Using this solution with GridBagLayout where the last component should fill all available space does not work! Am I missing something? – DjSol Mar 20 '14 at 15:16
  • @Kylar This is genius, but now one of my JTextArea, which was filling the Panel by BorderLayout.CENTER does not work anymore (shrinked to minimum size). Do you have any clue how to fix this? – Haeri Aug 13 '15 at 01:10
  • Trim it down to a small example and post a second question. – Kylar Aug 13 '15 at 17:16
  • @Kylar Thanks. here is the post: http://stackoverflow.com/questions/32008604/jtextarea-inside-jpanel-inside-jscrollpane if you want to take a look ;) – Haeri Aug 14 '15 at 11:09
1

You should add a Viewport for your scrollPane :

scrollPane.setViewportView(textArea)
joey rohan
  • 3,505
  • 5
  • 33
  • 70
  • How's that possible whenever my 'innerContainer' contains multiple JTextArea's, or any other J-component? – Velth Apr 03 '13 at 09:52
  • @MarkvanVelthoven Fair question.But it works when you add a view port(I checked on your SSCCE by removing multiple textarea).Have to think about multiple textAreas.Nice question btw. – joey rohan Apr 03 '13 at 10:02
  • @MarkvanVelthoven also, problem wont come if you assign different scrollbars to different textareas ! – joey rohan Apr 03 '13 at 10:07
  • but I'd like to have a JPanel with multiple JTextArea's and scroll the entire JPanel. Rather I do not have a JScrollPane per JTextArea, if that would be possible :-) – Velth Apr 03 '13 at 10:49
  • @MarkvanVelthoven You can do `VERTICAL/HORIZONTAL_SCROLLBAR_NEVER` like that it won't be visible...Try, if not i will try to give an SSCCE – joey rohan Apr 03 '13 at 11:57
0

Use

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

It wraps the text and avoids horizontal scrollpane.

And try GridBagLayout. Use weightx and weighty. It will take care of resize problems

Mohan Raj B
  • 1,015
  • 7
  • 14
0

JTextArea never shrinks when line wrap is enabled

I have a JTextArea in a JPanel with Gridlayout that has this problem. Mine was solved by simply setting the TextArea minimum size.

textArea.setMinimumSize(new Dimension(20,40));
bob
  • 35
  • 6