tags:

views:

69

answers:

5

Hi,

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 textfields 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?

+1  A: 

I would look at miglayout. It's a lot more useful than any of the inbuilt layout managers.

Gordon
+1  A: 

Yeah, MiGLayout is nice. You can do pretty much anything with it.

Michael Angstadt
+1  A: 

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.

Durandal
+2  A: 

MiGLayout has a lot of appeal, but BoxLayout is an alternative. http://i46.tinypic.com/35jjnh0.png

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();
            }
        });
    }
}
trashgod
YES. Great. Thanks!
thepandaatemyface
The only problem I have now is that when the labels in one box are different, the textboxes are differently sized, like so http://grab.by/5gpW . is there a way of fixing this without writing my own LayoutManager?
thepandaatemyface
@thepandaatemyface: Yes, the default layout for the `inner` `JPanel()` is plain ol' `FlowLayout`, but I like `new JPanel(new FlowLayout(FlowLayout.TRAILING))`. Alternatively, `new BoxLayout(inner, BoxLayout.X_AXIS)` lets you use all the alignment features mentioned in the tutorial.
trashgod
@thepandaatemyface: I've updated the example to show one approach.
trashgod
A: 

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

Tom Hawtin - tackline