1

I would like to add a key listener events to 3 of my TextFields:

angleText, initialVelocityText, and accelerationText

I would like to reject characters except for decimal dots and also keep backspaces, and also accept numbers.

Thank you in advance - This has been fixed - Thanks especially to @AliGul for his response and thanks to the others too

This is the code from the class I am talking about:

package projectV1;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.*;






public class Simulation extends JPanel {
//Initialise all the variables
private int BOX_WIDTH = 1920;
private int BOX_HEIGHT = 1080;

public String angle, distance, height , acceleration, initialVelocity, velocity, time; // Keep all as string until calc
public int x, y ,vx, vy;
private boolean isRunning; 
public JFrame simFrame;
public JPanel  inputPanel;
public Animate animatePanel;
public JButton start, apply;
public boolean validation = false;
    public static TextField accelerationText;
    public static TextField angleText;
    public static TextField initialVelocityText;
    public static TextField velocityText;
    public static TextField distanceText;
    public static TextField timeText;
    public static TextField heightText;


//FOR THE APPLY BUTTON JUST HAVE ONE OF THOSE BUT HAVE MULTIPLE BOXES WHICH YOU CAN CHANGE THE VALUE OF


// This will have my JPanel for the animatePanel, the animate panel will have the next class acting on it for the
// animation of the program.
// SO now we have the 2 panels that we need, in the bottom panel we will have the buttons and text fields, 
// will be variable holders and can be changed, we need to figure out the logic of how that will come to working.

public Simulation() {


    simFrame = new JFrame("Simulation");
     Main.setJFrame(simFrame);
     inputPanel = new JPanel(new GridLayout(2,7));
     animatePanel = new Animate();
     inputPanel.setBackground(Color.WHITE);
     animatePanel.setBackground(Color.LIGHT_GRAY);
     simFrame.add(inputPanel, BorderLayout.NORTH);
     simFrame.add(animatePanel, BorderLayout.CENTER);
     gui();

    }
  public void gui(){
    JLabel a,b,c,d,e,f,g; // These are just initialising the JLabels for the text fields

    // WHAT i attempted to do here is to make it so that adding these variables gets the things

    time = "0";
     acceleration = "9.81";
     initialVelocity = "10";
     distance = "0";
     height = "0";
     velocity = "0";
     angle = "45";
     // Place all the swing elements, I use a grid layout

     a = new JLabel("Current Velocity: ",JLabel.CENTER);
     a.setToolTipText("The velocity that the ball is currently moving at");
     inputPanel.add(a);
     velocityText = new TextField(velocity);
     inputPanel.add(velocityText);

     b = new JLabel("Current Distance:  ",JLabel.CENTER);
     b.setToolTipText("What the distance horizontally that the ball is travelling at");
     inputPanel.add(b);
     distanceText = new TextField(distance);
     inputPanel.add(distanceText);

     c = new JLabel("Current Height: ",JLabel.CENTER);
     c.setToolTipText("The current vertical height of the ball");
     inputPanel.add(c);
     heightText = new TextField(height);
     inputPanel.add(heightText);

     d = new JLabel("Current Time Elapsed: ",JLabel.CENTER);
     d.setToolTipText("The time elapsed, this relates to the motion of the ball");
     inputPanel.add(d);
     timeText = new TextField(time);
     inputPanel.add(timeText);

     e = new JLabel("Input Initial Velocity ",JLabel.CENTER);
     e.setToolTipText("How fast should the ball start as?");
     inputPanel.add(e);
     initialVelocityText = new TextField(initialVelocity);


     inputPanel.add(initialVelocityText);

     f = new JLabel("Input Acceleration",JLabel.CENTER);
     f.setToolTipText("Whats the acceleration); 9.81 is due to gravity on earth, try 1.6, its the moon's");
     inputPanel.add(f);
     accelerationText = new TextField(acceleration);
     inputPanel.add(accelerationText);

     g = new JLabel("Input angle (degrees): ",JLabel.CENTER);
     g.setToolTipText("Angle of attack? Please enter a value between 1 and 90");
     inputPanel.add(g);
     angleText = new TextField(angle);

     inputPanel.add(angleText);

     apply = new JButton("Apply Changes"); // This will apply changes put in text fields.
     inputPanel.add(apply);

     start = new JButton("Start Simulation"); // This will apply and start the timer and send all the variables.
     inputPanel.add(start);

     apply.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e){
             apply();
         }
     });
     start.addActionListener(new ActionListener(){
         public void actionPerformed(ActionEvent e){
             apply();
             simulate(acceleration, angle, initialVelocity);
              }
     });
      }

  private void apply(){ // ADD VALIDATION FOR THIS BEFORE THE CODE IS DONE
    int count = 0;

    angle = angleText.getText();
    if (validateAngle(angle)){
        count = count +1;
    }
    angle = convertToRadians(angle);
    acceleration = accelerationText.getText();
    if (validateAcceleration(acceleration)){
        count = count +1;
    }
    initialVelocity = initialVelocityText.getText();
    if (validateInitialVelocity(initialVelocity)){
        count = count +1;
        }
    if (count ==3){
        validation = true;
    }
    }

public void simulate(String acceleration, String angle, String initialVelocity){


    // apply();
    if (validation){

    animatePanel.start(acceleration, initialVelocity, angle);
    } else {
        JOptionPane.showMessageDialog(animatePanel, "Re-enter values");
    }
    }

public String convertToRadians(String angle){ // Does a conversion to get the angle in degrees to radians.
    double angleToRadians = 0;
    angleToRadians = Double.parseDouble(angle);
    angleToRadians = (Math.PI*angleToRadians)/180;
    angle = Double.toString(angleToRadians);
    return angle;
}

public boolean validateAcceleration(String acceleration){
    double tempAcc = Double.parseDouble(acceleration);
    if (isDouble(acceleration)){
        if (tempAcc>0){
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }

    }


public boolean validateAngle(String angle){
    double tempAngle = Double.parseDouble(angle);
    if (isDouble(angle)){
        if (tempAngle>=1 && tempAngle<= 90){
            return true;
        } else {
            return false;
        }
        } else {
        return false;
    }

}


public boolean validateInitialVelocity(String initialVelocity){
    double tempVel = Double.parseDouble(initialVelocity);
    if (isDouble(initialVelocity)){
        if (tempVel >1){
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

public boolean isDouble(String str) {
    try {
        Double.parseDouble(str);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

}

3 Answers3

1

I would like to reject characters except for decimal dots and also keep backspaces, and also accept numbers.

KeyListener is not the appropriate mechanism to achieve this (in fact KeyListener is generally not the appropriate mechanism for a lot of things), instead you should be using a DocumentFilter

There are countless examples:

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Have you tried using a focusListener ?

In short you would check when the focus is lost on either text fields, and validate wether the input fits your requirements, using a special method and a RegExp for your constraints.

Or you could use a FormattedTextField

Community
  • 1
  • 1
Webster
  • 164
  • 3
0

Hope this helps.

angleText.addKeyListener(new KeyAdapter() { //disables everything except number and dots
        public void keyTyped(KeyEvent e) {
            char input = e.getKeyChar();
            if ((input < '0' || input > '9') && input != '\b' && input != '.') {
                e.consume(); 
            }
        }
    });

Then, just change the 'angleText' part to 'initialVelocityText' etc.

Ali Gul
  • 115
  • 1
  • 11
  • 1
    `KeyListener` is a poor choice, there's no guarantee that the key stroke won't already have been committed to the `Document` and does not take into account what happens when a user pastes text into the field – MadProgrammer Apr 27 '17 at 10:51
  • You can use this to disable the copy and paste functions. angleText.setTransferHandler(null); @MadProgrammer – Ali Gul Apr 27 '17 at 10:53
  • @AliGul Well, doesn't that just ruin the user experience – MadProgrammer Apr 27 '17 at 10:57
  • This is working for what I need it to, just for a small scale project. Again thank you very much Ali Gul – Haris Rabbani Apr 27 '17 at 10:58
  • MadProgrammer thank you for the input, it is appreciated – Haris Rabbani Apr 27 '17 at 10:58
  • @MadProgrammer It depends on what you're developing, really. If it's a small and simple project, it shouldn't be a problem. – Ali Gul Apr 27 '17 at 11:01
  • @HarisRabbani No problem! Thanks for choosing my answer as the best one. :) – Ali Gul Apr 27 '17 at 11:01
  • No worries, I have added the fix and it is working well. Thank you again @AliGul – Haris Rabbani Apr 27 '17 at 11:05
  • @AliGul The problem is, as I stated, that there's no guarantee that the `KeyListener` will be notified in the same order on all platforms or that consuming the key will work as expected - and yes, I've debugged both these issues. There are also other APIs available, which are designed to just what the OP is asking. Users also have expectations, but if you like users cursing your name, that's a choice you have to make – MadProgrammer Apr 27 '17 at 11:06
  • @MadProgrammer Noted. I'm still 'fairly' new to Java so I have a lot of new things to learn. Thanks for the heads up. – Ali Gul Apr 27 '17 at 11:11