javaformsswingspringlayout

Java Swing Complex Form - SpringLayout


I need help creating a Java swing form. The form is dynamically created and asks the user for various inputs. The inputs vary and could be Textfields, RadioButton, ComboBox. I'm trying to determine what is the best layout for such a form. Currently, I have something like:

JPanel pnlForm = new JPanel(new SpringLayout());

for (Parameter p : globals) {
  JLabel lblName = new JLabel(p.getName() + ": ", JLabel.TRAILING);
  pnlForm.add(lblName);

  // The input field depends on parameter type
  if (p.getType().equals("filename")) {
    JPanel pnlFileChooser = new JPanel();
    JTextArea txtArea = new JTextArea(p.getValue());
    JButton btnFileChooser = new JButton("Browse");
    pnlFileChooser.add(txtArea);
    pnlFileChooser.add(btnFileChooser);
    pnlForm.add(pnlFileChooser);
  } else if (p.getType().equals("textbox")) {
    JTextArea txtArea = new JTextArea(p.getValue());
    pnlForm.add(txtArea);
  } else if (p.getType().equals("checkbox")) {
     // not yet implemented
  } else if (p.getType().equals("radio")) {
     ButtonGroup bgRadios = new ButtonGroup();
     for(String option : p.getSelections()){
        JRadioButton btnOption = new JRadioButton(option);
        btnOption.setMnemonic(KeyEvent.VK_B);
        btnOption.setActionCommand(option);
        bgRadios.add(btnOption);
        pnlForm.add(btnOption);
     }
  } else {
    JLabel lblError = new JLabel("ERROR! Unknown type!" + p.getType());
    lblName.setLabelFor(lblError);
    pnlForm.add(lblError);
  }

    //Lay out the panel.
    SpringUtilities.makeCompactGrid(pnlDetails, 
            globals.size() - 1, 2, //rows, cols
            1, 1,  //initX, initY
            5, 5); //xPad, yPad

This is currently coming up very choppy (the radio buttons wont stay in the same area). Any thoughts on how I could make this layout better?

Thanks!

[edit]

Adding the following diagram as to what this may look like. The gray lines can be ignored, just there to show where a JPanel might be. Each row is dynamically generated based on some user input. How can I make a form that looks like this?

enter image description here


Solution

  • I ended up getting this working using the SpringLayout with two panels on each row. The left panel contains the label and the right contains the input field. This seems to work well:

        for (Parameter p : params) {
            // The label for this parameter
            JLabel pname = new JLabel(p.getName() + ": ", JLabel.TRAILING);
    
            // Setup the sub panels for this layout, aligned to point each other
            JPanel pnlLeft = new JPanel(new FlowLayout(FlowLayout.RIGHT));
            JPanel pnlRight = new JPanel(new FlowLayout(FlowLayout.LEFT));
    
            // The value field for this parameter, depends on param type
            if (p.getType().equals("filename")) {
                JButton btnBrowse = new JButton("Browse");
                btnBrowse.setActionCommand(pfilepath + p.getId());
                btnBrowse.addActionListener(this);
                JTextField pvalue = new JTextField(p.getValue(),50);
                pnlRight.add(pvalue);
                pnlRight.add(btnBrowse);
            } else if (p.getType().equals("directory")) {
                JButton btnBrowse = new JButton("Browse");
                btnBrowse.setActionCommand(pdirpath + p.getId());
                btnBrowse.addActionListener(this); 
                JTextField pvalue = new JTextField(p.getValue(),50);               
                pnlRight.add(pvalue);
                pnlRight.add(btnBrowse);            
            } else if (p.getType().equals("textbox")) {
                JTextField pvalue = new JTextField(p.getValue(),50);
                pnlRight.add(pvalue);            
            } else if (p.getType().equals("checkbox")) {
                for(String option : p.getSelections()){
                    JCheckBox chkbox = new JCheckBox(option);
                    if (p.getValue().contains(option)){
                        chkbox.setSelected(true);
                    }
                    chkbox.setName(p.getId() + "_" + option);
                    chkbox.setActionCommand(pchkbox + p.getId() + "_" + option);
                    chkbox.addActionListener(this);
                    pnlRight.add(chkbox);
                }
            } else if (p.getType().equals("radio")) {
                ButtonGroup bgRadios = new ButtonGroup();
                for(String option : p.getSelections()){
                    JRadioButton radio = new JRadioButton(option);
                    if (p.getValue().equals(option)){
                        radio.setSelected(true);
                    }
                    radio.setName(p.getId() + "_" + option);
                    radio.setActionCommand(pradio + p.getId() + "_" + option);
                    radio.addActionListener(this);                    
                    bgRadios.add(radio);
                    pnlRight.add(radio);
                }
            } else {
                JTextField pvalue = new JTextField(p.getValue(),50);
                pvalue.setText("ERROR! Invalid global parameter type!" + p.getType());
                pvalue.setEditable(false);
                pnlRight.add(pvalue);
            }
    
            // Add subpanels to this main panel and set labeling
            pnlLeft.add(pname);
            pname.setLabelFor(pnlRight);
            add(pnlLeft);
            add(pnlRight);
        }
    
        // Correctly setup SpringLayout grid for this main panel
        SpringUtilities.makeCompactGrid(this, 
                params.size(), 2, //rows, cols
                1, 1,  //initX, initY
                1, 1); //xPad, yPad