ליאל אלמליח
ליאל אלמליח

Reputation: 19

Key Event on Thread java

I was required to show the user a random character and check from the moment the character is displayed whether the user types it before it disappears and another character is displayed. I was able to do this, but used in THREAD test is not actually carried out. Here is my code:

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

import javax.swing.*;

  public class MyThread extends Frame implements Runnable{
    String abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private JLabel lbl;  
    JPanel contentPane;
    public Random rnd;

    public MyThread() {
        lbl = new JLabel("Hello world");
        contentPane = new JPanel(null);

        setFocusable(true);
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                if (KeyEvent.getKeyText(keyCode) == lbl.getText()) {
                    System.out.println("nice");
                }
                else
                    System.out.println("not");

                  repaint();             

            }

        });

        add(lbl);
        setSize(200,100);
        setLocation(300,300);


        rnd = new Random();
        setVisible(true);

    }  

    public void run() {

        try {
          while (true) {
            if (lbl.getText() == null)
              lbl.setText(Character.toString(abc.charAt(rnd.nextInt(26))));
            else
              lbl.setText(null);

            Thread.sleep(900);
          }
        }
        catch (InterruptedException ex) {
        }
      }



    public static void main(String []args){
        new Thread(new MyThread()).start();

    }
  }

What is the problem and how can I fix it? Thank you..

Upvotes: 0

Views: 613

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

You've got several problems in that code:

  • You're mixing AWT (e.g., Frame) with Swing unnecessarily
  • You're starting your Swing GUI off of the Swing event thread
  • You're adding a KeyListener to a Frame object
  • Your code disobeys Swing threading rules by changing Swing component state off of the event thread.
  • You're comparing Strings with the == operator, an operator that checks for reference equality, something you really aren't interested. Strings should be compared instead with the .equals(...) or .equalsIgnoreCase(...) methods, methods which check for functional equality -- that the two Strings hold the same chars in the same order, which is what you want.
  • You're using a while (true) loop when a much better construct is to use a javax.swing.Timer or "Swing Timer".

e.g.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class MyGui extends JPanel {
    private static final char[] ABC = "ABCDEFGHIJKLMNOPQURSTUVWXYZ".toCharArray();
    private static final int PREF_W = 250;
    private static final int PREF_H = 150;
    private static final int TIMER_DELAY = 900;
    private JLabel label = new JLabel();
    private DefaultListModel<String> statusListModel = new DefaultListModel<>();
    private JList<String> statusList = new JList<>(statusListModel);

    public MyGui() {
        JPanel centerPanel = new JPanel(new GridBagLayout());
        centerPanel.add(label);
        setPreferredSize(new Dimension(PREF_W, PREF_H));

        statusList.setPrototypeCellValue("   GOOD   ");
        JScrollPane statusPane = new JScrollPane(statusList);
        statusPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        setLayout(new BorderLayout());
        add(centerPanel, BorderLayout.CENTER);
        add(statusPane, BorderLayout.LINE_END);

        new Timer(TIMER_DELAY, new TimerListener()).start();

        setFocusable(true);
        requestFocusInWindow();

        addKeyListener(new MyKeyListener());
    }

    private class MyKeyListener extends KeyAdapter {
        @Override
        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();
            String keyText = KeyEvent.getKeyText(keyCode).toUpperCase();
            if (keyText.equals(label.getText())) {
                statusListModel.addElement("good");
            } else {
                statusListModel.addElement("bad");
            }
            statusList.ensureIndexIsVisible(statusListModel.size() - 1);
        }
    }

    private class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            String text = label.getText();
            if (text.isEmpty()) {
                int randomIndex = (int) (ABC.length * Math.random());
                text = String.valueOf(ABC[randomIndex]);
                label.setText(text);
            } else {
                label.setText("");
            }
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("MyGui");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new MyGui());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

Upvotes: 3

Related Questions