After inserting values in JTextField, their random value is not shown. How can I fix it?

Tags: , , ,



I wrote this Java Application which is used to extract a random value from those entered in the JTextFields after starting a counter. Compiles and gives no errors, but the ("" +randomElement) value is not displayed.

I created the randomElement property inside the TimerListener class in the actionPerformed() method which starts the counter. At the end of the count the random value taken from the four JTextFields must be shown (as you can see from the code below).

Could you tell me where I’m wrong and how can I fix it?

public class Merge extends JPanel {
    public static final int TIMER_DELAY = 1000;
    public static final String TEST_TEXT = "123456";
    public JTextField textField = new JTextField(16);
    public JButton button = new JButton(new ButtonAction());
    public Timer timer;
    JTextField t1Text = new JTextField();
    JTextField t2Text = new JTextField();
    JTextField t3Text = new JTextField();
    JTextField t4Text = new JTextField();
    JLabel f1Label = new JLabel("Filippo film 1");
    JLabel f2Label = new JLabel("Filippo film 2");
    JLabel l1Label = new JLabel("Laura film 1");
    JLabel l2Label = new JLabel("Laura film 2");

    public Merge() {
        add(button);
        add(textField);
    }

    public static void main(String[] args) {
        Merge me = new Merge();
        me.createAndShowGui();
    }

    public void createAndShowGui() {
        Merge mainPanel = new Merge();
        JFrame frame = new JFrame("Film roulette");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.setLayout(new GridLayout(11, 4));
        frame.pack();
        frame.setBounds(100, 10, 400, 400);
        frame.add(f1Label);
        frame.add(t1Text);
        frame.add(f2Label);
        frame.add(t2Text);
        frame.add(l1Label);
        frame.add(t3Text);
        frame.add(l2Label);
        frame.add(t4Text);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public class ButtonAction extends AbstractAction {

        public ButtonAction() {
            super("The movie you will see...");
            putValue(MNEMONIC_KEY, KeyEvent.VK_P);
        }

        @Override
        public void actionPerformed(ActionEvent e) {

            if (timer != null && timer.isRunning()) {
                return;
            }
            textField.setText("");
            timer = new Timer(TIMER_DELAY, new TimerListener());
            timer.start();
        }
    }

    private class TimerListener implements ActionListener {
        private String text = "";
        private int counter = 0;

        @Override
        public void actionPerformed(ActionEvent e) {
            
            String filmFilippo1, filmFilippo2, filmLaura1, filmLaura2;

            filmFilippo1 = t1Text.getText();
            filmFilippo2 = t2Text.getText();
            filmLaura1 = t3Text.getText();
            filmLaura2 = t4Text.getText();

            List<String> givenList = Arrays.asList(filmFilippo1, filmFilippo2, filmLaura1, filmLaura2);
            Random rand = new Random();
            String randomElement = givenList.get(rand.nextInt(givenList.size()));
            
            text += TEST_TEXT.charAt(counter);
            textField.setText(text);
            counter++;
            if (counter >= TEST_TEXT.length()) {
                timer.stop();
                textField.setText("" +randomElement);
            }
        }
    }
}

Answer

To answer your actual question the reason its empty is because you do this in createAndShowGui:

Merge mainPanel = new Merge();
// ...
frame.getContentPane().add(mainPanel);

You create a new instance of your Merge class which you then add to the JFrame which you already did in main(string[] args):

public static void main(String[] args) {
    Merge me = new Merge();
    me.createAndShowGui();
}

So now you have 2 instances of the Merge class in which one is not visible to the user. You should simply do this in createAndShowGui:

frame.getContentPane().add(this);

HOWEVER

  1. Don’t extend JPanel unnecessarily
  2. Create all Swing components on the EDT via SwingUtilities.invokeLater
  3. Use JFrame#setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); so it completely exits the application unless you only want to dispose?
  4. Call JFrame#pack() only after adding all components
  5. Don’t call setBounds yourself you are using a LayoutManager leave it to that!
  6. No need to call JFrame#getContentPane()#add simply call JFrame#add
  7. You choose a random number for every tick of the timer, why not just choose it once at the end of the timer?
  8. You may also want to disable your textField which counts as people could put input there and mess with your codes logic lol
  9. Don’t declare or initialize variables globally unless they are needed in different methods

enter image description here

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Merge {

    public static final int TIMER_DELAY = 1000;
    public static final String TEST_TEXT = "12345";
    private int counter = 1;
    private Random rand = new Random();
    private Timer timer;

    public Merge() {
        createAndShowGui();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Merge::new);
    }

    private void createAndShowGui() {
        JFrame frame = new JFrame("Film roulette");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // create components
        JTextField textField = new JTextField(16);
        JButton button = new JButton("The movie you will see...");
        button.setMnemonic(KeyEvent.VK_P);
        JPanel mergePanel = new JPanel();
        JTextField t1Text = new JTextField();
        JTextField t2Text = new JTextField();
        JTextField t3Text = new JTextField();
        JTextField t4Text = new JTextField();
        JLabel f1Label = new JLabel("Filippo film 1");
        JLabel f2Label = new JLabel("Filippo film 2");
        JLabel l1Label = new JLabel("Laura film 1");
        JLabel l2Label = new JLabel("Laura film 2");

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (timer != null && timer.isRunning()) {
                    return;
                }

                // gather user input
                List<String> givenList = Arrays.asList(t1Text.getText(), t2Text.getText(), t3Text.getText(), t4Text.getText());

                // reset fields (if button is clicked more then once)
                textField.setText("");
                counter = 0;

                // start a timer
                timer = new Timer(TIMER_DELAY, (ActionEvent ev) -> {
                    if (counter >= TEST_TEXT.length()) {
                        ((Timer) ev.getSource()).stop();
                        String randomElement = givenList.get(rand.nextInt(givenList.size()));
                        textField.setText(randomElement);
                    } else {
                        textField.setText(textField.getText() + TEST_TEXT.charAt(counter));
                        counter++;
                    }
                });

                timer.start();
            }
        });

        // layout components
        mergePanel.add(button);
        mergePanel.add(textField);
        frame.add(mergePanel);
        frame.setLayout(new GridLayout(11, 4));
        frame.add(f1Label);
        frame.add(t1Text);
        frame.add(f2Label);
        frame.add(t2Text);
        frame.add(l1Label);
        frame.add(t3Text);
        frame.add(l2Label);
        frame.add(t4Text);
        frame.setLocationByPlatform(true);

        frame.pack();
        frame.setVisible(true);
    }
}


Source: stackoverflow