0

I'd like to have a GUI that can adapt to user input, rather than making a different panel for each option.

The first panel has a number of buttons to choose from, each will bring you to the next panel that will contain text entry fields.

Option A: Has 2 components and should open a panel with 4 text fields.

Option B: Has 3 components and should open a panel with 6 text fields.

Specifically, option A is a recipe with two components, and option B is a recipe with 3 components. Each component has a lot number and an expiration date. So both panels will have the same two types of fields: lot number and expiration date. The number and names of components is what will change.

Can I have the same panel be able to adapt to a number of components sent to it based on which of the two options was selected? Or do I have to make two separate panels, one with 4 fields and one with 6?

Here's one idea:

Map<String, JTextField> fieldMap = new HashMap<String, JTextField>()
for(int i = 0; i < recipe.length; i++)
{
    fieldMap.put("field" + i, new JTextField());
}

Idea derived from Creating a variable name using a String value

4
  • 2
    It is probably easiest to have two panels, and swap between them using a CardLayout as needed. I say probably as I'm not clear on the nature of these labels and field combos. What are the labels? Are the first two the same between the panels? Commented Dec 9, 2021 at 17:03
  • @AndrewThompson I just edited it to be more accurate. Specifically, option A is a recipe with two components, and option B is a recipe with 3 components. Each component has a lot number and an expiration date. So both panels will have the same two types of fields: lot number and expiration date. The number and names of components is what will change. Commented Dec 9, 2021 at 20:57
  • 1
    I would recommend having the 2 label & field pairs and a JList or JTable for the rest of the changeable information. Either of the latter allows multiple selections (e.g. as to whether the consumer wants 'cream on tip', 'gluten-free option' or a 'sprinkle of cocoa'). Edit: So one single panel. Just changing the field values and model (of the list or table) should do the trick. Commented Dec 10, 2021 at 2:26
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. Commented Dec 16, 2021 at 5:50

1 Answer 1

1

The code below addresses specifically your question statement, although I can't help thinking that you probably want something more generic, i.e. where there are more than two options. Also, the below code is only one possible implementation of your stated requirements.

The idea in the below code is to initially create all the required GUI components in a single container and simply change the visibility of the [optional] components depending on the selected option.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerDateModel;

public class Opciones implements ActionListener {
    private JFrame  frame;
    private JLabel  expiryThirdLabel;
    private JLabel  lotThirdLabel;
    private JRadioButton  twoRadioButton;
    private JRadioButton  threeRadioButton;
    private JSpinner  expiryFirstSpinner;
    private JSpinner  expirySecondSpinner;
    private JSpinner  expiryThirdSpinner;
    private JTextField  lotFirstTextField;
    private JTextField  lotSecondTextField;
    private JTextField  lotThirdTextField;

    public void actionPerformed(ActionEvent event) {
        Object src = event.getSource();
        boolean flag;
        if (twoRadioButton == src) {
            flag = false;
        }
        else if (threeRadioButton == src) {
            flag = true;
        }
        else {
            flag = false;
            JOptionPane.showMessageDialog(frame,
                                          "Unrecognized source.",
                                          "WARNING",
                                          JOptionPane.WARNING_MESSAGE);
        }
        expiryThirdLabel.setVisible(flag);
        expiryThirdSpinner.setVisible(flag);
        lotThirdLabel.setVisible(flag);
        lotThirdTextField.setVisible(flag);
        frame.pack();
    }

    private void createAndDisplayGui() {
        frame = new JFrame("Options");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(createTopPanel(), BorderLayout.PAGE_START);
        frame.add(createForm(), BorderLayout.CENTER);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createForm() {
        JPanel form = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets.bottom = 5;
        gbc.insets.left = 5;
        gbc.insets.right = 5;
        gbc.insets.top = 5;
        JLabel lotFirstLabel = new JLabel("Lot Number");
        form.add(lotFirstLabel, gbc);
        gbc.gridx = 1;
        lotFirstTextField = new JTextField(6);
        form.add(lotFirstTextField, gbc);
        gbc.gridx = 2;
        JLabel expiryFirstLabel = new JLabel("Expiry");
        form.add(expiryFirstLabel, gbc);
        gbc.gridx = 3;
        expiryFirstSpinner = createSpinner();
        form.add(expiryFirstSpinner, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        JLabel lotSecondLabel = new JLabel("Lot Number");
        form.add(lotSecondLabel, gbc);
        gbc.gridx = 1;
        lotSecondTextField = new JTextField(6);
        form.add(lotSecondTextField, gbc);
        gbc.gridx = 2;
        JLabel expirySecondLabel = new JLabel("Expiry");
        form.add(expirySecondLabel, gbc);
        gbc.gridx = 3;
        expirySecondSpinner = createSpinner();
        form.add(expirySecondSpinner, gbc);

        gbc.gridx = 0;
        gbc.gridy = 2;
        lotThirdLabel = new JLabel("Lot Number");
        lotThirdLabel.setVisible(false);
        form.add(lotThirdLabel, gbc);
        gbc.gridx = 1;
        lotThirdTextField = new JTextField(6);
        lotThirdTextField.setVisible(false);
        form.add(lotThirdTextField, gbc);
        gbc.gridx = 2;
        expiryThirdLabel = new JLabel("Expiry");
        expiryThirdLabel.setVisible(false);
        form.add(expiryThirdLabel, gbc);
        gbc.gridx = 3;
        expiryThirdSpinner = createSpinner();
        expiryThirdSpinner.setVisible(false);
        form.add(expiryThirdSpinner, gbc);

        return form;
    }

    private JSpinner createSpinner() {
        SpinnerDateModel sdm = new SpinnerDateModel();
        JSpinner spinner = new JSpinner(sdm);
        spinner.setEditor(new JSpinner.DateEditor(spinner, "MM/dd/yyyy")); // USA format
        return spinner;
    }

    private JPanel createTopPanel() {
        JPanel topPanel = new JPanel();
        JLabel label = new JLabel("Number of Components");
        topPanel.add(label);
        ButtonGroup buttonGroup = new ButtonGroup();
        twoRadioButton = new JRadioButton("Two");
        twoRadioButton.addActionListener(this);
        twoRadioButton.setSelected(true);
        buttonGroup.add(twoRadioButton);
        topPanel.add(twoRadioButton);
        threeRadioButton = new JRadioButton("Three");
        threeRadioButton.addActionListener(this);
        buttonGroup.add(threeRadioButton);
        topPanel.add(threeRadioButton);
        return topPanel;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new Opciones().createAndDisplayGui());
    }
}

Initially, the GUI looks like this

two screen capture

And after selecting Three radio button

three screen capture

Refer to the following.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, you're correct that this isn't quite as flexible as what I'm looking for, but it's a good start. I'm thinking something more adaptable, like Map<String, JTextField> fieldMap = new HashMap<String, JTextField>() for(int i = 0; i < recipe.length; i++) { fieldMap.put("field" + i, new JTextField()); } Idea for this derived from stackoverflow.com/questions/8631935/…
Edited the question to post the code up there

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.