Accessing JComboBox data from separate JForm

房东的猫 提交于 2019-12-01 20:51:49

What I'm suggesting is that you create two JPanel classes, one that holds your JComboBox, and the other that displays or otherwise needs the results. Assuming you've done that and called the first class, HoldsComboBoxPanel, and your second class is called ShowSelectionPanel, then you would give the HoldsComboBoxPanel two methods, one to get the current selection, a "getter" method, and another to allow outside classes to add an ActionListener to the combobox. For instance in brief, something like so:

public class HoldsComboBoxPanel extends JPanel {
   public static final String NAME = "holds combobox panel";
   // sample data
   private static final String[] DATA = { "Monday", "Tuesday", "Wednesday",
         "Thursday", "Friday" };
   private JComboBox<String> comboBox = new JComboBox<>(DATA);

   public HoldsComboBoxPanel() {
       // add the comboBox into our class here
   }

   // method to add a listener
   public void addComboBoxListener(ActionListener listener) {
      comboBox.addActionListener(listener);
   }

   // getter method
   public String getComboSelection() {
      return (String) comboBox.getSelectedItem();
   }

}

Your second class, the one that needs the data would have a setter method to allow outside classes the ability to push the combo selection into it. Assuming it had a JTextField called displayField that showed the selection, its code could look like so:

public class ShowSelectionPanel extends JPanel {
   public static final String NAME = "show selection panel";
   private JTextField displayField = new JTextField(10);

   public ShowSelectionPanel() {
      // add the displayField to the JPanel here
   }

   // setter method
   public void setDisplayText(String text) {
      displayField.setText(text);
      // or do whatever else you want to do with the selection
   }
}

Then you'd have another class that used CardLayout and that allowed swapping between the view JPanels above, say called MainPanel. It could use the CardLayout to allow you to swap JPanels, have a public method to allow outside classes to swap "card" JPanels, and it would hold both a HoldsComboBoxPanel field and a ShowSelectionPanel field, and could link them by adding the ActionListener to the combobox like so:

public class MainPanel extends JPanel {
   private CardLayout cardLayout = new CardLayout();
   private MenuPanel menuPanel = new MenuPanel();
   private HoldsComboBoxPanel holdsComboBoxPanel = new HoldsComboBoxPanel();
   private ShowSelectionPanel showSelectionPanel = new ShowSelectionPanel();

   public MainPanel() {
      // add an ActionListener to the JComboBox
      holdsComboBoxPanel.addComboBoxListener(new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            // get the combo's selected String
            String selection = holdsComboBoxPanel.getComboSelection();
            if (selection != null) {
               // push it into showSelection
               showSelectionPanel.setDisplayText(selection);
            }
         }
      });

      setLayout(cardLayout);
      add(menuPanel, MenuPanel.NAME);
      add(holdsComboBoxPanel, HoldsComboBoxPanel.NAME);
      add(showSelectionPanel, ShowSelectionPanel.NAME);
   }

   // method that allows outside classes to swap views
   public void showCard(String key) {
      cardLayout.show(this, key);
   }
}

The whole thing with some additional code to allow movement through the "cards" could look something like this:

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class SimpleMultPanels {
   private static void createAndShowGui() {
      // create JFrame
      JFrame frame = new JFrame("SimpleMultPanels");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

      // add our MainPanel to the JFrame
      frame.getContentPane().add(new MainPanel());
      frame.pack(); // pack it
      frame.setLocationByPlatform(true);
      frame.setVisible(true); // show it
   }

   public static void main(String[] args) {
      // this is for starting our Swing app on the event thread
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class MainPanel extends JPanel {
   private CardLayout cardLayout = new CardLayout();

   // the three "card" JPanels that this JPanel displays:
   private MenuPanel menuPanel = new MenuPanel();
   private HoldsComboBoxPanel holdsComboBoxPanel = new HoldsComboBoxPanel();
   private ShowSelectionPanel showSelectionPanel = new ShowSelectionPanel();

   // Actions for our JButtons
   private ExitAction exitAction = new ExitAction();
   private ShowAction backToMenuAction = new ShowAction(this, "Back to Menu",
         MenuPanel.NAME, KeyEvent.VK_B);
   private ShowAction toHoldsComboAction = new ShowAction(this, "Combo Panel",
         HoldsComboBoxPanel.NAME, KeyEvent.VK_C);
   private ShowAction toShowSelectionAction = new ShowAction(this,
         "Show Selection", ShowSelectionPanel.NAME, KeyEvent.VK_S);

   public MainPanel() {
      // add an ActionListener to the JComboBox
      holdsComboBoxPanel.addComboBoxListener(new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            // get the combo's selected String
            String selection = holdsComboBoxPanel.getComboSelection();
            if (selection != null) {
               // push it into showSelection
               showSelectionPanel.setDisplayText(selection);
            }
         }
      });

      // add Actions to class to allow swapping of cards and
      holdsComboBoxPanel.addButtonAction(backToMenuAction);
      holdsComboBoxPanel.addButtonAction(toShowSelectionAction);
      holdsComboBoxPanel.addButtonAction(exitAction); // and to exit gui

      showSelectionPanel.addButtonAction(backToMenuAction);
      showSelectionPanel.addButtonAction(toHoldsComboAction);
      showSelectionPanel.addButtonAction(exitAction);

      menuPanel.addButtonAction(toHoldsComboAction);
      menuPanel.addButtonAction(toShowSelectionAction);
      menuPanel.addButtonAction(exitAction);

      setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

      // set our layout
      setLayout(cardLayout);

      // and add our "card" JPanels
      add(menuPanel, MenuPanel.NAME);
      add(holdsComboBoxPanel, HoldsComboBoxPanel.NAME);
      add(showSelectionPanel, ShowSelectionPanel.NAME);
   }

   // method that allows outside classes to swap views
   public void showCard(String key) {
      cardLayout.show(this, key);
   }
}

@SuppressWarnings("serial")
class HoldsComboBoxPanel extends JPanel {
   // constant String that will be used by the CardLayout
   public static final String NAME = "holds combobox panel";

   // sample data
   private static final String[] DATA = { "Monday", "Tuesday", "Wednesday",
         "Thursday", "Friday" };
   private JComboBox<String> comboBox = new JComboBox<>(DATA);

   // JPanel to hold buttons to allow moving between cards
   private JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));

   public HoldsComboBoxPanel() {
      comboBox.setSelectedIndex(-1);
      JPanel centerPanel = new JPanel();
      centerPanel.add(comboBox);

      setLayout(new BorderLayout());
      add(centerPanel, BorderLayout.CENTER);
      add(buttonPanel, BorderLayout.SOUTH);
   }

   // method to add a listener
   public void addComboBoxListener(ActionListener listener) {
      comboBox.addActionListener(listener);
   }

   // getter method
   public String getComboSelection() {
      return (String) comboBox.getSelectedItem();
   }

   // create a new JButton with an Action and add to buttonPanel
   public void addButtonAction(Action action) {
      buttonPanel.add(new JButton(action));
   }
}

@SuppressWarnings("serial")
class ShowSelectionPanel extends JPanel {
   public static final String NAME = "show selection panel";
   private static final int PREF_W = 300;
   private static final int PREF_H = PREF_W;
   private JTextField displayField = new JTextField(10);
   private JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));

   public ShowSelectionPanel() {
      displayField.setFocusable(false);

      JPanel centerPanel = new JPanel();
      centerPanel.add(displayField);

      setLayout(new BorderLayout());
      add(centerPanel, BorderLayout.CENTER);
      add(buttonPanel, BorderLayout.SOUTH);
   }

   // code to make our GUI a little larger
   @Override
   public Dimension getPreferredSize() {
      Dimension superSz = super.getPreferredSize();
      if (isPreferredSizeSet()) {
         return superSz;
      }
      int prefW = Math.max(superSz.width, PREF_W);
      int prefH = Math.max(superSz.height, PREF_H);
      return new Dimension(prefW, prefH);
   }

   // setter method
   public void setDisplayText(String text) {
      displayField.setText(text);
      // or do whatever else you want to do with the selection
   }

   public void addButtonAction(Action action) {
      buttonPanel.add(new JButton(action));
   }

}

@SuppressWarnings("serial")
class MenuPanel extends JPanel {
   public static final String NAME = "menu panel";
   private JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 0, 5));

   public MenuPanel() {
      setLayout(new GridBagLayout());
      add(buttonPanel);
   }

   public void addButtonAction(Action action) {
      buttonPanel.add(new JButton(action));
   }
}

@SuppressWarnings("serial")
class ShowAction extends AbstractAction {
   private MainPanel mainPanel;
   private String key;

   /**
    * Abstract Action used by JButtons
    * @param mainPanel: the JPanel that uses the CardLayout
    * @param name: The name displayed by the button
    * @param key: The key used in the CardLayout#show(String key) mehtod
    * @param mnemonic: the JButton's mnemonic char
    */
   public ShowAction(MainPanel mainPanel, String name, String key, int mnemonic) {
      super(name);
      putValue(MNEMONIC_KEY, mnemonic);
      this.mainPanel = mainPanel;
      this.key = key;
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      // tell the mainPanel to show the card associated with the key
      mainPanel.showCard(key);
   }
}

// class of mine to allow disposing of a window
// It's a little complex to allow it to work with either a JButton
// or a JMenuItem
@SuppressWarnings("serial")
class ExitAction extends AbstractAction {
   public ExitAction() {
      super("Exit");
      putValue(MNEMONIC_KEY, KeyEvent.VK_X);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      // get the button that caused this action
      Object source = e.getSource();
      if (source instanceof AbstractButton) {
         AbstractButton exitButton = (AbstractButton) source;

         // get the parent top level window
         Window topWindow = SwingUtilities.getWindowAncestor(exitButton);
         if (topWindow == null) { // if null, then likely in a JMenuItem
            // so we have to get its jpopupmenu parent
            Container parent = exitButton.getParent();
            if (parent instanceof JPopupMenu) {
               JPopupMenu popupMenu = (JPopupMenu) parent;

               // get the invoker for the pop up menu
               Component invoker = popupMenu.getInvoker();
               if (invoker != null) {
                  // and get *its* top level window
                  topWindow = SwingUtilities.getWindowAncestor(invoker);
               }
            }
         }
         if (topWindow != null) {
            // dispose of the top-level window
            topWindow.dispose();
         }
      }
   }
}

If you just wont to send data to DefineEquation class, you should use your constructor with String argument in nextActionPerformed:

    new DefineEquation((String)graphSelection.getSelectedItem()).setVisible(true);

instead of:

    new DefineEquation().setVisible(true);

Also you need to chenge you constructor to:

public DefineEquation(String graphSelected) {
    this.graphSelected = graphSelected;
    initComponents();
}

Because right now without initComponents() it will display empty frame. At last, you need to setText() to JTextField in DefineEquation class, for example by:

 selectedGraph = new javax.swing.JTextField(graphSelected);

Do not use addItem()method, or rewrite it, becouse it creates new DefineEquation object which is unnecessary an even harmful. This way in new frame it display JTextField with chosen text. It worked for me, at least if I understood your problem correctly.

However, I would rather use enums instead of plain String, as they are more reliable. Your function set is constant, so you can create for example:

public enum Functions {NONE,LINEAR,BILINEAR,QUADRIATIC,CUBIC,EXPONENTIAL;}

This will required change of constructor, and JComboBox content, but you would be able to use it in whole application. Tou can call toString() or name() where you need String to display, but use enums in event handling, etc. I think you should also reconsider your approach to multiple JFrames, as suggested in comments. I also would not recommend that, but it is up to you. Good luck!

EDIT

If you dont't want to change initComponents() in DefineEquation, you can still modify addItem() like this:

public void addItem(){
    selectedGraph.setText(graphSelected);
}

but then you call call addItem() in constructor, to fill your JTextField with chosen text. Or you can pass graphSelected as argument of method, if so it don't have to be a class field.

So I was really dumb and had two instances created, one of which I was not viewing and the other of which I was but was not changing. Basically what I did was in graphSelectionActionPerformed I did:

this.graphSelectionGUI = (String)graphSelection.getSelectedItem();

Then in nextActionPerformed I did:

new DefineEquation_1(graphSelectionGUI).setVisible(true);

Following this, in the other class (DefineEquation), I took my constructor and did this:

public DefineEquation(String graphSelected) {
    this.graphSelected = graphSelected;
    initComponents();
    selectedGraph.setText(graphSelected);
}

And lastly I cried with tears realising how much trouble I gave you guys and how dumb I was, praise the lord!

Sorry for troubling everyone, my bad.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!