1

I'm trying to do as the title says.

I've got an efficient way for posting several of the same swing objects to a frame by storing them in an array and adding them using a for loop like so:

JLabel[] contrllabels= new JLabel[8];
contrllabels[0] = new JLabel("SCF Type: ");
contrllabels[1] = new JLabel("Units: ");
contrllabels[2] = new JLabel("Spherical Harmonics: ");
contrllabels[3] = new JLabel("Molecular Charge: ");
contrllabels[4] = new JLabel("PP: ");
contrllabels[5] = new JLabel("DFT Type: ");
contrllabels[6] = new JLabel("Max Iterations: ");
contrllabels[7] = new JLabel("Mult: ");


for(int i = 0;i<contrllabels.length;i++){
    c.gridy = i;
    frame.add(contrllabels[i],c);
}

But what if there are several swing objects of different types? I've got several combo boxes and textfields which I'd like to be added to the frame in a similar manner. I use gridbaglayout so if I don't use a for loop, I end up with lots of unnecessary code due to giving the constraints new values every time I want a different object added.

Is there such thing as an array of references which point to these different objects which I can then iterate through to add to the frame? Something like

JTextField tf = new JTextField(5);
JComboBox cb = new JComboBox("example");

Swing[] array = {tf,cb}

for(int i = 0;i<array.length;i++){
    c.gridy = i;
    frame.add(array[i],c);
}

I know such an array doesn't exist, but is there some way of implementing such a thing? It would greatly reduce the number of lines in my code and make it less confusing.

Thank you

user1147964
  • 143
  • 2
  • 11
  • at the very least, you can have Object arrays. I suggest you use an ArrayList though. You may find yourself needing to remove a object in the future and you'll be shifting all of your elements...wasting a lot of time! ArrayList is backed by an array and the slightly extra overhead is meaningless on the machines we run these days...and even phones! You should consider reading java.util.ArrayList code to see how it operates and you'll get a better feel of it all. – vinnybad Jan 13 '12 at 16:58

2 Answers2

7

You could use an array or collection of a common super type such as an array or ArrayList of JComponent. I'm curious if you're using a parallel array of GridBagConstraints to go with each component that is being added -- ugh. I often use arrays of components but usually if they are like components such as JLabel/JTextField pairs or a cluster of JRadioButtons.

As an aside, for my money, I try to avoid GridBagLayout as much as possible and instead nest containers that use the more coder-friendly layouts.

For instance this small GUI was made with a combination of FlowLayout, BoxLayout, BorderLayout and GridLayout:

enter image description here

The large JPanel that holds the whole GUI uses BorderLayout, The JTextArea in the center is placed BorderLayout.CENTER, the Provider JLabel and JTextField at the top are in a FlowLayout JPanel that is placed overall BorderLayout.NORTH, the bottom buttons are in a JPanel that uses GridLayout(1, 0, 5, 0) which is held in another JPanel that uses FlowLayout which is placed in the GUI BorderLayout.SOUTH, and the stuff on the right are in a BoxLayout using JPanel.

For example:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;

@SuppressWarnings("serial")
public class GetLetterTextGui extends JPanel {
   private static final int TA_ROWS = 20;
   private static final int TA_COLS = 35;
   private static final int PROVIDER_FIELD_COLS = 10;
   private static final String GUI_TITLE = "Get Letter Text";
   private JList letterList;
   private JTextArea textarea = new JTextArea(TA_ROWS, TA_COLS);
   private JTextField providerField = new JTextField(PROVIDER_FIELD_COLS);
   private JCheckBox addValedictionChkBox = new JCheckBox("Add Valediction", true);

   public GetLetterTextGui() {
      letterList = new JList(new String[]{"Fe", "Fi", "Fo", "Fum"});

      providerField.setText("John Smith, MD");

      textarea.setWrapStyleWord(true);
      textarea.setLineWrap(true);

      JPanel northPanel = new JPanel();
      northPanel.add(new JLabel("Provider:"));
      northPanel.add(providerField);

      JPanel southPanel = new JPanel();
      JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0));
      btnPanel.add(new JButton("Copy to Clipboard"));
      btnPanel.add(new JButton("Clear"));
      btnPanel.add(new JButton(new ExitAction()));
      southPanel.add(btnPanel);

      JPanel eastPanel = new JPanel();
      eastPanel.setLayout(new BoxLayout(eastPanel, BoxLayout.PAGE_AXIS));
      eastPanel.add(new JScrollPane(letterList));
      eastPanel.add(new JPanel() {{add(addValedictionChkBox);}});

      int eb = 0;
      setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
      setLayout(new BorderLayout(eb, eb));
      add(northPanel, BorderLayout.PAGE_START);
      add(eastPanel, BorderLayout.LINE_END);
      add(new JScrollPane(textarea), BorderLayout.CENTER);
      add(southPanel, BorderLayout.PAGE_END);
   }


   private class ExitAction extends AbstractAction {
      private final Object MNEMONIC = new Integer(KeyEvent.VK_X);

      public ExitAction() {
         super("Exit");
         putValue(MNEMONIC_KEY, MNEMONIC);
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         Window win = SwingUtilities.getWindowAncestor(GetLetterTextGui.this);
         win.dispose();
      }
   }

   private static void createAndShowGui() {
      GetLetterTextGui mainPanel = new GetLetterTextGui();

      JFrame frame = new JFrame(GUI_TITLE);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      try {
         for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
               UIManager.setLookAndFeel(info.getClassName());
               break;
            }
         }

         SwingUtilities.invokeLater(new Runnable() {
            public void run() {
               createAndShowGui();
            }
         });

      } catch (ClassNotFoundException e) {
         e.printStackTrace();
      } catch (InstantiationException e) {
         e.printStackTrace();
      } catch (IllegalAccessException e) {
         e.printStackTrace();
      } catch (UnsupportedLookAndFeelException e) {
         e.printStackTrace();
      }
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Which layouts do you use instead? To tell you the truth I'm finding a lot of these layouts to be very frustrating to work with. Thanks – user1147964 Jan 13 '12 at 15:51
  • @Hovercraft Full Of Eels `if you're using a parallel array of` imaging that hmmm +1 – mKorbel Jan 13 '12 at 15:52
  • Your solution worked Hovercraft. Thank you very much for the help. I'll experiment with a different combination of layouts – user1147964 Jan 13 '12 at 15:58
  • +1 for nested layouts; there's a related example [here](http://stackoverflow.com/a/3175280/230513). – trashgod Jan 13 '12 at 16:05
4

All GUI components are JComponent objects. ArrayList<JComponent> can hold references to all of them. Give it a try:

JFrame frame = new JFrame("test");
ArrayList<JComponent> cps = new ArrayList<JComponent>();
cps.add(new JLabel("Hello"));
cps.add(new JPanel());
cps.add(new JButton("OK"));

for (JComponent widget : cps) {
  frame.add(widget);
}
DejanLekic
  • 18,787
  • 4
  • 46
  • 77