I have example Java Swing code below that produces the following screenshot (screenshot has been edited to make it smaller):
Here is the code:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class Main extends JFrame {
public Main() {
JListTest theGui = new JListTest();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
add(theGui);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Main();
}
});
}
private class JListTest extends JPanel {
private static final int PADDING = 3;
private JLabel label;
private JTextArea textarea;
private String listOptions[] =
{"here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
"here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text",
"here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
"here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text",
"here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
"here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text",
"here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
"here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text",
"here is some veeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrry long text",
"here is some more loooooooooooooooooooooooooooooooooooooooooooooooooooooong text"};
private JList<String> list;
private JScrollPane scrollpane;
private GridBagConstraints gbc;
public JListTest() {
super(new GridBagLayout());
label = new JLabel("Here is a label:");
textarea = new JTextArea(20, 50);
list = new JList<String>(listOptions);
scrollpane = new JScrollPane(list);
gbc = new GridBagConstraints();
gbc.gridheight = 1;
gbc.insets = new Insets(PADDING, PADDING, PADDING, PADDING);
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridwidth = 4;
gbc.gridx = 0;
gbc.gridy = 0;
add(label, gbc);
// I want the scrollpane to take up 1/4 the width of the window.
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 1;
add(scrollpane, gbc);
// I want the textarea to take up 3/4 the width of the window.
gbc.gridwidth = 3;
gbc.gridx = 1;
gbc.gridy = 1;
add(textarea, gbc);
}
}
}
As you can see, I have a JList containing items with very long text inside of a JScrollPane on the left, and a JTextArea on the right. I would like the JScrollPane/JList to take up 1/4 of the window's width and have a horizontal scrollbar appear when the text of the JList items gets too long. I would like the JTextArea to take up 3/4 of the window's width.
I tried to do this with the GridBagLayout, but obviously I am not doing it right since the appearance is off.
Any help is appreciated. Thanks!
GridBagLayout
wants to work with the preferred size's of the components, this is one of those weird points where what you think you can do and what you actually can do conflict.
Essentially, what you want to do, is override the layout decisions that GridBagLayout
is making with your own logic (you take 25% of the width and you take 75% of the width). The problem is, GridBagLayout
doesn't think that way, it thinks more along the lines of, you can have 25% of the space which is left over after I've calculated everybody's preferred layout requirements and you can have 75%. This doesn't always come out the way you initially thought it should.
The first step, is to make use of weightx
and weighty
// I want the scrollpane to take up 1/4 the width of the window.
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 1;
gbc.weightx = 0.25;
gbc.weighty = 1;
add(scrollpane, gbc);
// I want the textarea to take up 3/4 the width of the window.
gbc.gridx = 1;
gbc.gridy = 1;
gbc.weightx = 0.75;
add(textarea, gbc);
This provides sizing hints to GridBagLayout
in what it should do with any left over space it might have after it's done it's initial layout.
But, wait, this doesn't seem to change anything! No, actually it doesn't, unless you resize the window enough, as I said, the components are layed out (as best as it can) to their preferred size. So the JList
and the JTextArea
are wrangling things against us.
A JScrollPane
get's it's preferred size from the view component. JList
implements the Scrollable
interface which provides a getPreferredScrollableViewportSize
method, which is used by the JScrollPane
as it's preferred size (otherwise it uses the components preferred size)
So, we can now get a little cheeky and modify the preferred viewport width...
list = new JList<String>(listOptions) {
@Override
public Dimension getPreferredScrollableViewportSize() {
Dimension size = super.getPreferredScrollableViewportSize();
size.width = 100;
return size;
}
};
(ps, I did test setFixedCellWidth
and setPrototypeCellValue
, but both these prevented the horizontal scroll bars from been presented).
Okay, this works a little better :P. There is a time where the minimum size will compete with the preferred size, so beware of that :P
Remember though, weightx/y
only works with the remaining space, it does not effect the initial layout :P