2

I've been trying to get a scrollable JTextArea to appear to the right of a JList where the JTextArea takes up most of the space but leaves a good portion for the JList (3/4 of the frame for the JTextArea, 1/4 for the JList). The problem is that the weights of the constraints seem to be ignored when LineWrap on the JTextArea is set to true.

Without line wrap, the JTextArea takes up about 3/4 of the frame and the JList takes up the other 1/4, which is what I want. But when line wrapping is turned on, the JTextArea attempts to take up as much space as possible and crushes the JList down to the width of the strings it contains. The interesting thing is that this only appears to happen once you resize the window (looks fine initially), and if you type anything into the JTextArea, it slowly expands, pushing the JList back. This has been confusing me to say the least.

I made a screenshot of what it looks like without line wrapping and with line wrapping after resizing the window: Example

Here's some example code showing you what I mean. Remove the line wrap statements and it'll look fine, but keep them there and you'll see that upon resizing, the JList is squished.

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.*

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel(new GridBagLayout());

        JTextArea area = new JTextArea();
        DefaultListModel<String> model = new DefaultListModel<>();
        JList<String> list = new JList<String>(model);
        JScrollPane scroll = new JScrollPane(area,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        for (int i = 0; i < 5; i++)
            model.addElement("Example" + i);

        area.setLineWrap(true);
        area.setWrapStyleWord(true);

        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1;
        c.weightx = 0.3;
        panel.add(scroll, c);

        c = new GridBagConstraints();
        c.gridx = 1;
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1;
        c.weightx = 0.1;
        panel.add(list, c);

        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 300);
        frame.setVisible(true);

    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Jack
  • 181
  • 1
  • 8
  • 2
    You can use the `JTextArea(rows, columns)` constructor to set a preferred size for your text area. The list will take up the remaining space – Paul Samsotha May 22 '14 at 10:00

4 Answers4

2

You can use ipadx to define minimal possible width

    c.weightx = 0.1;
    c.ipadx=desiredPixelsWidthForTheList;
    panel.add(list, c);

UPDATE

Also you can place both in a JSplitPane and define desired proportions.

StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • 2
    and/or with new JTextArea(10, 15); – mKorbel May 22 '14 at 10:08
  • I ended up just using a JSplitPane instead and letting the user decide the sizes of each so I'll accept this one. The JSplitPane doesn't appear to function perfectly, but well enough that it's basically unnoticeable and the user can move it to their liking. – Jack May 23 '14 at 06:08
2

The short answer is that the text area gets more width than you want because its preferred width is much larger than that of the list.

Keep in mind that weightx doesn't determine what percentage of space a component will occupy but the proportional amount of space that's added to or taken away from the component's size. In this case, for example, the "extra" space is the difference between the frame's width (or more accurately, its content pane's width) which you explicitly set to 500 and the combined widths of the text area and the list. In other words, both the scroll pane / text area and the list will be displayed at their preferred sizes PLUS 75% of the left-over space for the text area and 25% for the list. Again, since the text area's preferred size is large to begin with, it occupies a bigger portion of the screen than what you want.

As a couple of people have already pointed out, a simple way to get the results you want is to explicitly specify the number of rows and columns for the text area. On the other hand, you should avoid explicitly setting a size, preferred or otherwise as discussed in questions like this.

As far as the mysteriously shrinking list goes, I suspect that's a bug in GridBagLayout. It seems to ignore the maximum size of the JList initially but then respects it when it lays out the components as a result of the frame resizing, which is why it suddenly shrinks and then never gets larger again. That's not normally an issue because like JTextArea, a JList is normally contained within a scroll pane, which is something you should probably also consider doing.

Community
  • 1
  • 1
Gimpy
  • 61
  • 5
  • Unfortunately, the same problem occurs when the JList is contained inside a JScrollPane, but thanks for your explanation of what weightx and weighty are really doing. – Jack May 22 '14 at 20:10
0

try using .setPreferredSize() to components

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Sarz
  • 1,970
  • 4
  • 23
  • 43
0

I have modified your code. Just specified the size of textarea and list like this

list.setPreferredSize(new Dimension(frame.getWidth()/4, frame.getHeight()));
area.setPreferredSize(new Dimension(frame.getWidth()*(3/4), frame.getHeight()));

check the full code below:

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Main {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel(new GridBagLayout());

        JTextArea area = new JTextArea();
        DefaultListModel model = new DefaultListModel();
        JList list = new JList(model);
        JScrollPane scroll = new JScrollPane(area,
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        for (int i = 0; i < 5; i++)
            model.addElement("Example" + i);
        frame.setSize(500, 300);

        list.setPreferredSize(new Dimension(frame.getWidth()/4, frame.getHeight()));
        area.setPreferredSize(new Dimension(frame.getWidth()*(3/4), frame.getHeight()));
        area.setLineWrap(true);
        area.setWrapStyleWord(true);

        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1;
        c.weightx = 0.3;


        panel.add(scroll, c);

        c = new GridBagConstraints();
        c.gridx = 1;
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1;
        c.weightx = 0.1;
        panel.add(list, c);

        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

    }
}
Arijit
  • 1,633
  • 2
  • 21
  • 35