Variable Layout in Swing
How would you go about getting a decent looking gui generated when you don't know how many components you will have and how big they will be?
A user, for instance, enters how many textfield开发者_Go百科s they want and which of those textfields are grouped in bordered panels and the program generates this.
I've been using GridLayout, but the problem is that it makes all cells of the same width and height, which is fine when all components have the same size, but when I, for example, have a textfield and a bordered panel with multiple fields, either the textfield gets stretched out or the panel is squeezed.
I would like all components to have their minimum size, but still, you know, usable.
Example of how it is now, using GridLayout, all fields are normal, one-line JTextFields where the panel titled date is totally squeezed (it has three fields in it) and the first level fields are way to big. Anyone have any pointers?
MiGLayout has a lot of appeal, but BoxLayout
is an alternative.
import java.awt.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;
public class BoxTest extends JPanel {
private List<JTextField> fields = new ArrayList<JTextField>();
public BoxTest() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
this.add(createPane(3, "One ", Color.red));
this.add(createPane(3, "Two ", Color.green));
this.add(createPane(10, "Three ", Color.blue));
}
private JPanel createPane(int n, String s, Color c) {
JPanel outer = new JPanel();
outer.setLayout(new BoxLayout(outer, BoxLayout.Y_AXIS));
outer.setBorder(BorderFactory.createLineBorder(c, 2));
for (int i = 0; i < n; i++) {
JPanel inner = new JPanel();
inner.setLayout(new BoxLayout(inner, BoxLayout.X_AXIS));
JLabel label = new JLabel(s + i + ":", JLabel.RIGHT);
label.setPreferredSize(new Dimension(80, 32));
inner.add(label);
JTextField tf = new JTextField("Stackoverflow!", 32);
inner.add(tf);
fields.add(tf);
outer.add(inner);
}
return outer;
}
private void display() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JScrollPane jsp = new JScrollPane(this,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
this.validate();
Dimension d = this.getPreferredSize();
d.height /= 2;
jsp.getViewport().setPreferredSize(d);
jsp.getVerticalScrollBar().setUnitIncrement(
this.getPreferredSize().height / fields.size());
f.add(jsp);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new BoxTest().display();
}
});
}
}
I would look at miglayout. It's a lot more useful than any of the inbuilt layout managers.
Your general goal - "usable component sizes" clashes with "unknown number". Make the number large enough and they won't fit any screen.
Overthink if you wouldn't be better off with using JTables (cells can be made editable) in conjuction with a JScrollPanel. If you want/must keep your approach of generating components, put the whole JPanel that contains your components into a JScrollPane, that way the components wont be squeezed to badly.
Yeah, MiGLayout is nice. You can do pretty much anything with it.
Minimum size in AWT and Swing is usually pointless. I suggest adding a panel to delegate minimum size to original preferred size, and possibly add a bit to the new preferred size. In GridBagLayout
add weights where you want additional space to go in the normal size. As Durandal mentions, popping up scroll bars around the top-level window beats squeezing the layout or going off the screen (I'm writing this on a Netbook, so I know about windows larger than the screen).
精彩评论