Pengibaby
Pengibaby

Reputation: 373

update JcomboBox after Array is updated

I have a JComboBox which displays the contents of an array in my main class, but I have a another class that has a function which changes the array based on user inputs. However the JComboBox does not update even though the array has been updated in the main class (I used a print to check that it does in fact update). Is there a way for the JComboBox to update as more items are added to the array or items are removed from the array?

This is the JComboBox in the main class, where buildingNames is the array storing information and will be updated.

private String[] buildingNames;

public mainWindow() {
    initialize();
}

private void initialize() {
    frame = new JFrame("Main Window");
    frame.setBounds(0, 0, 1280, 720);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(null);
    frame.setBackground(Color.WHITE);
    frame.setResizable(false);

    buildingNames = {"Costlemark","Science","Research"} //This will get updated

    DefaultComboBoxModel BuildingModel = new DefaultComboBoxModel(buildingNames);
    JComboBox selectBuilding = new JComboBox(BuildingModel);
    selectBuilding.setBounds(46, 82, 150, 40);
    frame.getContentPane().add(selectBuilding);
}

Upvotes: 1

Views: 582

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285403

Several solutions exist including:

  • Use an observer pattern to notify concerned objects when the array is updated, and then create a new model for the combo box, and load it into the combo when updates occur. This would be part of a larger Model-View-Controller program structure and is probably the way I'd go.
  • Create your own model class, extending the abstract combo box model class, one that uses the array itself, and one that again is notified when the array is changed.
  • Get rid of the array altogether and instead update the combo box model when and where needed

The details of any solution, including code would depend on the details of your current program.

Side recommendations:

  • Your combo box variable should not be declared locally within the initialize() method as that will make it invisible to the rest of the class, nor should any other object be assigned to a local variable that needs to have its state changed by the program. Declare the variable as a private instance field of the class.
  • Never set the bounds of your components or use null layouts but rather set properties (visible row count, prototype display value...) and allow the component to size itself.
  • If your array contents are likely going to change quite a bit during program ru, then you probably should be using a collection such as an ArrayList<String>, or even better, an ArrayList<Building> of your custom Building class.

For an example of the last recommendation where we just use the combo box model:

import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class BuildingTest extends JPanel {
    // model to hold all the building name strings
    private DefaultComboBoxModel<String> comboModel = new DefaultComboBoxModel<>(new String[] {"Foo", "Bar", "Baz"});
    private JComboBox<String> selectBuildingCombo = new JComboBox<>(comboModel);

    // text field to allow user to add more strings to model
    private JTextField entryField = new JTextField(10);
    private JButton enterBuildingBtn = new JButton("Enter Building Name");    

    public BuildingTest() {
        // the size of the combobox larger
        selectBuildingCombo.setPrototypeDisplayValue("abcdefghijklmnopqrstuv");
        add(selectBuildingCombo);
        add(new JLabel("Enter new building name:"));
        add(entryField);
        add(enterBuildingBtn);

        selectBuildingCombo.addActionListener(e -> {
            String selection = (String) selectBuildingCombo.getSelectedItem();
            if (selection != null) {
                System.out.println("Selected Item: " + selection);
            }
        });

        // occurs when user wants to add to combo model
        ActionListener enterBuildingListener = e -> {
            // get text from text field
            String text = entryField.getText().trim();
            if (!text.isEmpty()) {
                // if not empty, add to model
                comboModel.addElement(text);
                entryField.selectAll();
            }
        };

        // add this action listener to both the text field and the button
        enterBuildingBtn.addActionListener(enterBuildingListener);
        entryField.addActionListener(enterBuildingListener);
        enterBuildingBtn.setMnemonic(KeyEvent.VK_E);
    }

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

        JFrame frame = new JFrame("Building Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

Upvotes: 2

Related Questions