-1

I'm trying to learn the difference between Hashtable and HashMap and I'm trying to add specific prices to these items here. The goal is to print the price of the item selected from comboItem into txtPrice.

        String[] items = {"Select Item","Betta Fish","Snail","Supplies","Food"};
        comboGroup = new JComboBox<String>(items);
        comboGroup.addActionListener(this);
        comboGroup.setBounds(130,35,150,40);
        
        comboItem = new JComboBox<>();
        comboItem.setPrototypeDisplayValue("XXXXXXXXXXX");
        comboItem.setBounds(130,85,150,40);
        
        String[] subItems1 = {"Select Betta","Plakat","Halfmoon","Double Tail","Crown Tail"};
        subItems.put(items[1], subItems1);
        
        String[] subItems2 = {"Select Snail","Pond Snail","Ramshorn","Apple Snail","Assassin Snail"};
        subItems.put(items[2], subItems2);
                
        String[] subItems3 = {"Select Supply","Small Fine Net","Large Fine Net","Flaring Mirror","Aquarium Hose (1meter)"};
        subItems.put(items[3], subItems3);
        
        String[] subItems4 = {"Select Food","Daphnia","Tubifex","Mosquito Larvae","Optimum Pellets"};
        subItems.put(items[4], subItems4);
        comboGroup.setSelectedIndex(1);      
        
        //TextFields <- this is the attempt to add price to subItems value but commented out
        /*int[] items1price = {0,150,350,200,200};
        subItems.put(items[1], items1price);
        int[] items2price = {0,15,25,80,120};
        subItems.put(items[2], items2price);
        int[] items3price = {0,50,80,25,15};
        subItems.put(items[3], items3price);
        int[] items4price = {0,50,100,50,50};
        subItems.put(items[4], items4price);
        comboGroup.setSelectedIndex(1);
        */
        txtPrice = new JTextField();
        txtPrice.setBounds(130,135,150,40);

So far with my understanding from HashMap applying it to CLi and not in GUI, If I try HashMap<String,Integer> I can only print it altogether in a single line.

eg.

HashMap<String,Integer> item = new HashMap<String,Integer>();
item.put("Plakat",50);

CLi Prints:
Plakat=50

What I want is to print Plakat from selected comboItem then print 50 to txtPrice but I don't know how to do that.

The whole code is here: https://github.com/kontext66/GuwiPos GUI and Main.

Additional note: I am a beginner and I'm trying to understand Layout Manager for now, so the code here is a bit messy and literal.

beepmorp
  • 5
  • 8
  • 2
    Looking at your code on GitHub, you put `Strings` in your `JComboBoxes`. You can put complete Java objects in a `JComboBox`, like an item and its price. Oracle has a helpful tutorial, [Creating a GUI With Swing](https://docs.oracle.com/javase/tutorial/uiswing/index.html). Skip the Learning Swing with the NetBeans IDE section. The section you want to focus on now is the [How to Use Combo Boxes](https://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html) section. – Gilbert Le Blanc Feb 07 '22 at 10:27
  • 1
    *"The whole code is here:"* [Edit] to add a [mre] *here.* – Andrew Thompson Feb 07 '22 at 11:52

1 Answers1

1

Below is an example using JComboBox and HashMap to get the corresponding "prices" to specific items in the combo box. I would suggest going through the tutorial on How to Use Various Layout Managers and choose the ones that suit you best. As for the difference between HashMap and HashTable, please have a look at this answer. The main difference is that HashTable is synchronized, whereas HashMap is not, and since synchronization is not an issue for you, I'd suggest HashMap. Also, another option would be to add instances of a custom object to a JComboBox, as described here. Thus, there would be no need to use HashMap.

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;

public class App {
    Map<String, String> map;
    JTextField tf;

    public App() {
        map = new HashMap<String, String>();
        map.put("Plakat", "50");
        map.put("Halfmoon", "25");
        map.put("Double Tail", "80");
    }

    private void addComponentsToPane(Container pane) {
        String[] items = { "Select Item", "Plakat", "Halfmoon", "Double Tail" };
        JComboBox<String> comboBox = new JComboBox<String>(items);

        comboBox.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent event) {
                if (event.getStateChange() == ItemEvent.SELECTED) {
                    String item = (String) event.getItem();
                    System.out.println(item);
                    tf.setText(map.get(item));
                }
            }
        });

        tf = new JTextField();
        JPanel p = new JPanel();
        pane.add(comboBox, BorderLayout.NORTH);
        pane.add(tf, BorderLayout.SOUTH);
    }

    private void createAndShowGUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addComponentsToPane(frame.getContentPane());
        // frame.setSize(640, 480);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new App().createAndShowGUI();
            }
        });
    }

}

Update

Below is the implementation of the second approach described earlier, where a custom object is used for adding items to a JComboBox, and hence, there is no need to use a HashMap.

P.S. I should also add that if the user shouldn't be allowed to edit the "price" in the text field, then you should use tf.setEditable(false);, or even use a JLabel instead.

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

public class App {
    JTextField tf;

    class ComboItem {
        private String key;
        private String value;

        public ComboItem(String key, String value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public String toString() {
            return key;
        }

        public String getKey() {
            return key;
        }

        public String getValue() {
            return value;
        }
    }

    private void addComponentsToPane(Container pane) {
        JComboBox<ComboItem> comboBox = new JComboBox<ComboItem>();
        comboBox.addItem(new ComboItem("Select Item", ""));
        comboBox.addItem(new ComboItem("Plakat", "50"));
        comboBox.addItem(new ComboItem("Halfmoon", "25"));
        comboBox.addItem(new ComboItem("Double Tail", "80"));

        comboBox.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent event) {
                if (event.getStateChange() == ItemEvent.SELECTED) {
                    Object item = comboBox.getSelectedItem();
                    String value = ((ComboItem) item).getValue();
                    tf.setText(value);
                }
            }
        });

        tf = new JTextField();
        JPanel p = new JPanel();
        pane.add(comboBox, BorderLayout.NORTH);
        pane.add(tf, BorderLayout.SOUTH);
    }

    private void createAndShowGUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addComponentsToPane(frame.getContentPane());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new App().createAndShowGUI();
            }
        });
    }
}

Update 2

To convert the string from the text field into double, you can use Double.parseDouble(String), as shown below (again, make sure to use tf.setEditable(false);, so that the value cannot be modified by the user).

double price = 0;
if (tf.getText() != null && !tf.getText().trim().isEmpty())
    price = Double.parseDouble(tf.getText());
System.out.println(price);
Chris
  • 18,724
  • 6
  • 46
  • 80
  • The cleaner way to implement your second (better) solution is to not rely on `ComboBoxItem#toString`, but to create a custom `ComboBoxRenderer`. – daniu Feb 07 '22 at 12:23
  • Hi, considering that you used String for the prices eg. "20" can String values be used in math operations? Because I will also be implementing a `(Price * Quantity)` for the `total` in the future and since "20" is considered a String and not int/double I'm wondering if there will be any conflict. Thank you for the reference of `HashMap` vs `Hashtable`, it was very informative. – beepmorp Feb 08 '22 at 01:45
  • @daniu I tried switching `public String getValue()` to `public int` and I get `incompatible types: String cannot be converted to int` same with the line `tf.setText(value);` I tried to add a JSpinner for the quantity and it says `non-static method setText(String) cannot be referenced from a static context`. I posted the code here on GitHub for reference to leave this post relevant to title. [here](https://github.com/kontext66/ConnectingSwings/blob/main/comboBox) – beepmorp Feb 08 '22 at 03:25
  • Sorry tagged the wrong person, thanks @Chris the conversion update was really helpful. – beepmorp Feb 09 '22 at 01:22