Search code examples
javaswinguser-interfaceawtjlabel

How to also change int if Jlabel is changed


I am trying to figure out how I can also change my int if my Jlabel is changed. I tried to use AtomicInteger and it works if I only want to change n1, but how do I make it that it looks at the label and then changes the correct int? At the moment I have n1 - n3, but in the future that will be 30.

This is my code at the moment:

public class GUI {
    JLabel currentEditLabel = null;
    JFrame frame;
    int n1 = 6;
    int n2 = 5;
    int n3 = 8;

    GUI() {
        frame = new JFrame();//creating instance of JFrame
        JLabel l1 = new JLabel(Integer.toString(n1));
        JLabel l2 = new JLabel(Integer.toString(n2));
        JLabel l3 = new JLabel(Integer.toString(n3));
        JTextField t = new JTextField();

        l1.setBounds(40, 50, 100, 40);
        l2.setBounds(40, 100, 100, 40);
        l3.setBounds(40, 150, 100, 40);
        t.setBounds(20, 200, 100, 40);

        frame.add(l1);
        frame.add(l2);
        frame.add(l3);
        frame.add(t);

        t.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (currentEditLabel != null) {
                    currentEditLabel.setText(t.getText());
                    AtomicInteger level = new AtomicInteger(Integer.parseInt(currentEditLabel.getText()));
                    n1 = level.intValue();
                    currentEditLabel = null;
                }
            }
        });

        addMouseListener(l1, t);
        addMouseListener(l2, t);
        addMouseListener(l3, t);

        frame.setSize(400, 500);//400 width and 500 height
        frame.setLayout(null);//using no layout managers
        frame.setVisible(true);//making the frame visible
    }

    private void addMouseListener(JLabel label, JTextField t) {
        label.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                currentEditLabel = (JLabel) e.getComponent();
                t.setText(currentEditLabel.getText());
            }
        });
    }

    public static void main(String[] args) {
        new GUI();
    }
}

Solution

  • AtomicInteger? You're barking up the wrong tree since this won't help you in the least.

    Your n1 value does in fact change within the listener, but you're not changing the JLabel text at all, and that is what you need to do:

    • In the MouseListener, also call setText(...) on whatever JLabel (the one clicked perhaps) that you wish to have the text display change on.
    • While the l1 JLabel's displayed text is created using n1's value, note that if n1 ever changes, l1 s text will not change on its own. Again, if you wish to change l1's text, you must do so with code, calling .setText(...) on it.

    Some suggestions based on your new requirements:

    • Create an array of int to hold the int values
    • Create a List<JLabels> to hold all the JLabels that will display the values held in the above collection of numbers
    • Create your JLabels in a for loop that loops through all the ints, and fill each JLabel with the appropriate number text
    • In that same for loop, add your JLabels to the JLabel-list mentioned above
    • Add a MouseListener (I usually use a MouseAdapter for this) to each JLabel in the for loop
    • Pass the for loop's index into your MouseListener's constructor to set a field of the class, so that the index of the selected JLabel is readily available
    • Use a JSpinner and SpinnerNumberModel to display the changable text
    • In the MouseLister, set the value that the spinner holds
    • Add a ChangeListener to the spinner so that when the numeric value changes, you update the appropriate JLabel with the new value
    • You will need to also remove the above ChangeListener before setting the spinner's value in the mouse listener and then re-add the same listener immediately after making this change.
    • Do not use AtomicInteger as it is completely unnecessary and is somewhat misleading to you
    • Avoid using null layouts but instead use layout managers

    Proof of concept:

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.GridLayout;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.*;
    import javax.swing.border.Border;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    @SuppressWarnings("serial")
    public class GUI2 extends JPanel {
        private static final Border UNSELECTED_BORDER = BorderFactory.createLineBorder(Color.LIGHT_GRAY, 3);
        private static final Border SELECTED_BORDER = BorderFactory.createLineBorder(Color.PINK, 3);
        private int[] intArray = { 6, 5, 8, 13, 17, 22, 55, 33, 2, 0, 23, 51, 0, 111, 200, 6, 5, 8, 13, 17, 22, 55, 33, 2,
                0, 23, 51, 0, 111, 200, 6, 5, 8, 13, 17, 22, 55, 33, 2, 0, 23, 51, 0, 111, 200 };
        private SpinnerNumberModel spinnerModel = new SpinnerNumberModel(0, 0, 10000, 1);
        private JSpinner intSpinner = new JSpinner(spinnerModel);
        private ChangeListener spinnerListener = new SpinnerListener();
        private List<JLabel> labelList = new ArrayList<>();
        private int selectedIndex = -1;
    
        public GUI2() {
            JPanel topPanel = new JPanel();
            topPanel.add(new JLabel("Current Selected Value:"));
            topPanel.add(Box.createHorizontalStrut(5));
            topPanel.add(intSpinner);
            intSpinner.addChangeListener(spinnerListener);
    
            int gap = 3;
            JPanel labelGridPanel = new JPanel(new GridLayout(0, 5, gap, gap));
            for (int i = 0; i < intArray.length; i++) {
                String text = String.valueOf(intArray[i]);
                JLabel label = new JLabel(text);
                label.setBorder(UNSELECTED_BORDER);
                label.addMouseListener(new MyMouse(i));
                labelGridPanel.add(label);
                labelList.add(label);
            }
    
            setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
            setLayout(new BorderLayout(gap, gap));
            add(topPanel, BorderLayout.PAGE_START);
            add(labelGridPanel, BorderLayout.CENTER);
        }
    
        private class MyMouse extends MouseAdapter {
            private int index;
    
            public MyMouse(int index) {
                this.index = index;
            }
    
            @Override
            public void mousePressed(MouseEvent e) {
                selectedIndex = index;
                JLabel label = labelList.get(index);
                int currentValue = Integer.parseInt(label.getText());
    
                // remove change listener before making this change
                intSpinner.removeChangeListener(spinnerListener);
                intSpinner.setValue(currentValue);
                // then re-add the change listener after
                intSpinner.addChangeListener(spinnerListener);
    
                // show by border which JLabel has been selected
                for (JLabel jLabel : labelList) {
                    // first make all borders the default border
                    jLabel.setBorder(UNSELECTED_BORDER);
                }
                // then set the selected border
                labelList.get(index).setBorder(SELECTED_BORDER);
            }
        }
    
        private class SpinnerListener implements ChangeListener {
    
            @Override
            public void stateChanged(ChangeEvent e) {
                // if we have not yet selected a JLabel, get out of here
                if (selectedIndex < 0) {
                    return;
                }
                int value = (int) spinnerModel.getValue();
                labelList.get(selectedIndex).setText(Integer.toString(value));
            }
    
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> {
                GUI2 mainPanel = new GUI2();
    
                JFrame frame = new JFrame("GUI");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(mainPanel);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            });
        }
    
    }