简体   繁体   中英

How can I best lay out these components in Swing?

What would be the best approach / LayoutManager for a JPanel that needed to display the components shown in the image? (Note that the fields should resize horizontally when the size of the window is changed, but not the labels).

I'm currently trying (and struggling) to do it with a GridBagLayout. Is this the correct approach or is there a better way? Should I be trying to divide + conquer the seperate sections maybe?

Any thoughts or advice would be gratefully appreciated. :-)

http://img261.imageshack.us/img261/2091/layouthb6.png

PS If you read this and there's no image, please bear with me whilst I fix it!

I would look at nesting JPanels . It would be very easy to make each row a separate JPanel and then just stack the JPanels .

Otherwise you can use the GridBagLayout . That is the one I use for more control over where components are placed.

Using GridBagLayout you can layout a row by incrementing the GridBagConstraint .gridx and then resetting GridBagConstraint.gridx = 0 and GridBagConstraint.gridy++ to move to the next row.

I would suggest a third party free layout manager. MigLayout comes to mind (check the example form at the bottom of the linked page), or JGoodies FormLayout , which is especially good at formslike these.

The standard layout managers are good, but whoefully inadequate for frequent use for screens like these (the new GroupLayout used by the Matisse designer in Netbeans wasn't built for nothing). The linked layout managers are a lot easier to use and maintain IMHO.

I would definitly use DesignGridLayout :

DesignGridLayout layout = new DesignGridLayout(this);
layout.row().grid(label0).add(field0);
layout.emptyRow();
layout.row().grid(label1).add(field1);
layout.row().grid(label2).add(field2);
layout.row().grid(label3).add(field3);
layout.row().grid(label4).add(field4);
layout.emptyRow();
layout.row().grid(label5).add(field5).grid(label6).add(field6);
layout.row().grid(label7).add(field7).grid(label8).add(field8);
layout.emptyRow();
layout.row().grid(label9).add(field9);

Disclaimer: I am one of DesignGridLayout authors.

If you can use external code, take a look at the JGoodies layout managers.

Personally, I find GridBagLayout to be more trouble than it's worth -- to the extent that I've written my own layout managers to avoid it.

I personally prefer GroupLayout .

Even if you're not using a GUI builder you can use the layout by hand and it's fairly simple and straightforward to work with if you understand the concepts.

TableLayout would be my choice, you can use constants such as TableLayout.FILL for auto-resizing and specify pixel widths for fixed.

TableLayout

Your layout looks like it's essentially composed of "lines". So personally, I would:

  • Create a vertical Box with Box.createVerticalBox(); this will stack its components vertically-- in effect, let you add lines
  • Create a panel for each line: I think you could use a JPanel with a BorderLayout (and the label on the left, text field as the centre component), or again use Box.createHorizontalBox(), and add label and text field to that, with appropriate min/preferred size
  • You can add a "strut" to the vertical box where you need line separators
  • Your line with two groups of label/field needs a little bit of special treatment, but it's essentially just a horizontal box with TWO of your "lines" inside it.

Personally, I never touch GridBagLayout with a barge pole. Maybe it's just me, but I find concurrent algorithms and machine code programming easier than fathoming out GridBagLayout...

I used to really hate doing swing layouts until Netbeans came out with their gui builder. You can see a demo here. http://rghosting.co.cc

Since Java SE 6 you can use GroupLayout

It's very easy and looks just like you want.

For this window:

alt text http://img165.imageshack.us/img165/8237/sampleusinggrouplayoutca2.png

I have this code:

    // Layout the components using the new GroupLayout added
    // in java 1.6.
    // Adding to the main frame
    private void layoutComponents(){
        JPanel panel = new JPanel();

        GroupLayout layout = new GroupLayout(panel);
        panel.setLayout(layout);

        layout.setAutoCreateGaps(true);         
        layout.setAutoCreateContainerGaps(true);

        SequentialGroup hGroup = layout.createSequentialGroup();

        JLabel nameLbl  = new JLabel("Name");
        JLabel countLbl = new JLabel("Amount");
        JLabel dateLbl  = new JLabel("Date(dd/MM/yy)");
        hGroup.addGroup(layout.createParallelGroup().
                addComponent(nameLbl).
                addComponent(countLbl).
                addComponent(dateLbl).
                addComponent(go));

        hGroup.addGroup(layout.createParallelGroup().
                addComponent(name).
                addComponent(count).
                addComponent(date));

        layout.setHorizontalGroup(hGroup);

        SequentialGroup vGroup = layout.createSequentialGroup();

        vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                addComponent(nameLbl).
                addComponent(name));

        vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                addComponent(countLbl).
                addComponent(count));

        vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                addComponent(dateLbl).
                addComponent(date));

        vGroup.addGroup(layout.createParallelGroup(Alignment.BASELINE).
                addComponent(go));
        layout.setVerticalGroup(vGroup);

        frame.add( panel , BorderLayout.NORTH );
        frame.add( new JScrollPane( textArea ) );
    }

GridBagLayout is definitely the best choice for this. And NetBeans Matisse is probably the fastest way of achieving this. If you are using another IDE, just copy & paste the auto-generated code.

GridBagLayout , of course.

If the form is just this, then you done need more than one JPanel . (If you have buttons, you probably need one more, depending on where/how they are)

Field 0 - 4 and 9 will have gridwidth set to 4, others the default (1, but you need not set it to 1)

The 'spaces' between groups of fields can be achieved via insets.

(For this layout, at least) I would not suggest third party layout managers. GridBagLayout is not complex. It just takes (a li'l bit of) time to get used to it.

Visual Editor + Eclipse can do these for you easily. (I am not very comfortable with Netbeans and its swing development. Tried it, but never fell in love. Maybe, I am too much addicted to Eclipse)

I think, that of all standard layouts, GridBagLayout should be best for what you need.

You could try something like the following example, where I simplified the complex GridBagConstraints constructor to what I really need by using addToLayout.

If you can use an IDE though, this can really make things easier (Matisse in NetBeans for instance).

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

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class GridBagLayoutTest extends JPanel {

    public GridBagLayoutTest() {
        setLayout(new GridBagLayout());
        addToLayout(new JLabel(     "Label 0" ), 0, 0, 0d, 1);
        addToLayout(new JTextField( "Field 0" ), 0, 1, 1d, 4);
        addToLayout(new JLabel(     "*"       ), 0, 5, 0d, 1);
        addToLayout(new JPanel()               , 1, 0, 0d, 1);
        addToLayout(new JLabel(     "Label 1" ), 2, 0, 0d, 1);
        addToLayout(new JTextField( "Field 1" ), 2, 1, 1d, 4);
        addToLayout(new JLabel(     "*"       ), 2, 5, 0d, 1);
        addToLayout(new JLabel(     "Label 2" ), 3, 0, 0d, 1);
        addToLayout(new JTextField( "Field 2" ), 3, 1, 1d, 1);
        addToLayout(new JLabel(     "*"       ), 3, 2, 0d, 1);
        addToLayout(new JLabel(     "Label 3" ), 3, 3, 0d, 1);
        addToLayout(new JTextField( "Field 3" ), 3, 4, 1d, 1);
        addToLayout(new JLabel(     "*"       ), 3, 5, 0d, 1);
    }

    private void addToLayout(java.awt.Component comp, int y, int x, double weightx, int gridwidth) {
        add(comp, new GridBagConstraints(x, y, gridwidth, 1, weightx, 0d,
                                         GridBagConstraints.CENTER, GridBagConstraints.BOTH,
                                         new java.awt.Insets(2, 4, 2, 4), 0, 0 ) );
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new GridBagLayoutTest());
        frame.setSize(800, 600);
        frame.setVisible(true);
    }
}

You could describe the layout as a HTML table and then use this tool: http://www.onyxbits.de/content/blog/patrick/java-gui-building-gridbaglayout-manager-made-easy

To translate the layout into Java code for configuring a GridBagLayout.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM