0

So I wanted to validate the username (length should be between 6 to 30 characters, and numbers should not be allowed) that the user entered before the game proceeds, and I searched the internet and found out about the regex expressions. I am not used to it so I have found some problems. The code should do the following: if the user didn't enter a username or if it contained characters not allowed when he clicked the "start game" button, I wanted a dialog box to pop up and tell him to try again. And if everything was correct the game should proceed as normal, but when I run this code the username is not checked and it enters the game despite what is entered in the text box, and below is what I have so far.

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

import java.awt.Font;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.ActionEvent;
import java.util.regex.*;

public class StartScreen extends JFrame {

private JPanel contentPane;
private JTextField textbox_name;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                StartScreen frame = new StartScreen();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */

public static boolean isValidUsername(String name) 
{ 
    String regex = "^[a-zA-Z]{5,29}$";  //Removed ^[aA-zZ]\\\\w{5,29}$
    Pattern p = Pattern.compile(regex);     
    if (name == null) { 
        return false; 
    }   
    Matcher m = p.matcher(name);    
    return m.matches(); 
 } 

public StartScreen() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 455, 191);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);
    
    JLabel lblEnterName = new JLabel("Enter Name:");
    lblEnterName.setFont(new Font("Lucida Grande", Font.PLAIN, 15));
    lblEnterName.setBounds(91, 48, 102, 29);
    contentPane.add(lblEnterName);
    
    textbox_name = new JTextField();
    textbox_name.setBounds(205, 49, 130, 28);
    contentPane.add(textbox_name);
    textbox_name.setColumns(10);
    
    String field;
    field = textbox_name.getText();
    
    JButton btnStartGame = new JButton("Start Game");
    btnStartGame.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            
            if(isValidUsername(field)) {
                MainScreen window = new MainScreen();
                window.setVisible(true);
                dispose();
            }
            else {
                JOptionPane.showMessageDialog(null, "Please enter your username correctly");
            }
        }
    });
    
    
    
    btnStartGame.setBounds(150, 102, 117, 29);
    contentPane.add(btnStartGame);
}

}

  • Please check [this regex](https://regex101.com/r/7fS0bZ/1). Am I missing some requirements for username except that is composed only by letters and it has a minimum and maximum length? – marianc Aug 03 '20 at 18:07
  • That is exactly what is supposed to do, however when I run the code, I can enter whatever username I like and it enters directly into the game, instead of displaying a dialog box. – Joao Felipe Leal Aug 03 '20 at 18:10
  • Please check your if statement. I think you have it backwards. You have it only throwing the error if the btnStartGame.isEnabled() is true and the name check returns true. I think you meant to have it throw the error if false, correct? – Tim Hunter Aug 03 '20 at 18:16
  • That makes sense, so I did the following: if(btnStartGame.isEnabled() && (isValidUsername(field) == false)) However, when I do this it keeps showing the error despite what I write in the textbox. – Joao Felipe Leal Aug 03 '20 at 18:25
  • You may want to rework your logic on that. You want to structure it so that you are looking for the conditions where the game can start and throwing an error for everything else. So your `if` braces should hold the conditions under which the game will start and perform them. Your `else` should contain the code for throwing an error if the conditions under which it starts are not true. – Tim Hunter Aug 03 '20 at 18:31
  • It's an event that triggers when the button is clicked, correct? So you shouldn't need to check if the button is clicked since the event will only fire when it's clicked. You would just need to check the entered name value for validation. – Tim Hunter Aug 03 '20 at 18:34
  • I edited the code to the following and get errors despite what is entered, this should be working right?: `if(isValidUsername(field)) { MainScreen window = new MainScreen(); window.setVisible(true); dispose(); } else { JOptionPane.showMessageDialog(null, "Please enter your username correctly"); }` – Joao Felipe Leal Aug 03 '20 at 18:37
  • A side comment: You may want to make your error message have details about what a "correct username" is. Tell the user what the conditions for it being correct are so they actually know what to do to fix it. – Tim Hunter Aug 03 '20 at 18:39
  • I assume your `field` variable is a reference to the username input field, correct? Do you need to access the value inside the field? I assume just passing a reference to the field object won't give the actual value written into it. Most likely it's trying to read the object's `toString()` default value in that case instead of the written value. – Tim Hunter Aug 03 '20 at 18:42
  • That makes perfect sense, do you have any ideas on how to acquire the value inside the textfield then? If not I might research a bit more here – Joao Felipe Leal Aug 03 '20 at 18:49
  • Assuming you're using a `JTextField`, then the [getText()](https://stackoverflow.com/questions/5752307/how-to-retrieve-value-from-jtextfield-in-java-swing) method should be what you want. – Tim Hunter Aug 03 '20 at 18:51

2 Answers2

0

I tried your isValidUsername as a standalone method and it didn't give valid results. It was giving false even for valid names. I changed it to the following and it worked well:

public static boolean isValidUsername(String name) 
{ 
    String regex = "^[a-zA-Z]{5,29}$";  //Removed ^[aA-zZ]\\\\w{5,29}$
    Pattern p = Pattern.compile(regex);     
    if (name == null) { 
        return false; 
    }   
    Matcher m = p.matcher(name);    
    return m.matches(); 
 } 

Also, since the code is being executed after the button btnStartGame has been clicked, its not therefore possible that the button is disabled (A disabled button doesn't fire events). For that reason, I think the check if(btnStartGame.isEnabled()) is redundant (I may be wrong). You can hence just check:

if(sValidUsername(field)){
  //start game here
} else {
  //display prompt here
}
Kasalwe
  • 358
  • 2
  • 6
  • Just tried it and you are right that it is quite useless to have the button to isEnabled, however when I tried your change in my program I am still having the same error, which is that doesn't matter what is written the dialog box pops up. Maybe the error is in the isValidUsername method, but I just can't figure out what is wrong. – Joao Felipe Leal Aug 04 '20 at 15:09
  • @Joao, the isValidUsername() method works fine. You can try it as a stand alone. The code that you have posted doesn't reflect a working scenario. Because you have posted code that is not inside a method but meanwhile its at the same level as isValidUsername. Are you able to share the complete class having the code you posted? – Kasalwe Aug 05 '20 at 01:23
  • Sure, will edit the answer with my whole class so you can take a look. – Joao Felipe Leal Aug 05 '20 at 04:15
0

These two lines from the code you posted in your question:

String field;
field = textbox_name.getText();

need to be inside method actionPerformed() because you want to get the contents of textbox_name after the user clicks on the button btnStartGame.

Here is my rewrite of the code you posted.

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

import java.awt.Font;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.ActionEvent;
import java.util.regex.*;

public class StartScreen extends JFrame {

private JPanel contentPane;
private JTextField textbox_name;

/**
 * Launch the application.
 */
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                StartScreen frame = new StartScreen();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the frame.
 */

public static boolean isValidUsername(String name) 
{ 
    String regex = "^[a-zA-Z]{5,29}$";  //Removed ^[aA-zZ]\\\\w{5,29}$
    Pattern p = Pattern.compile(regex);     
    if (name == null) { 
        return false; 
    }   
    Matcher m = p.matcher(name);    
    return m.matches(); 
 } 

public StartScreen() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 455, 191);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    setContentPane(contentPane);
    contentPane.setLayout(null);
    
    JLabel lblEnterName = new JLabel("Enter Name:");
    lblEnterName.setFont(new Font("Lucida Grande", Font.PLAIN, 15));
    lblEnterName.setBounds(91, 48, 102, 29);
    contentPane.add(lblEnterName);
    
    textbox_name = new JTextField();
    textbox_name.setBounds(205, 49, 130, 28);
    contentPane.add(textbox_name);
    textbox_name.setColumns(10);
    
    JButton btnStartGame = new JButton("Start Game");
    btnStartGame.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            String field;  // added this line
            field = textbox_name.getText();  // added this line
            
            if(isValidUsername(field)) {
                MainScreen window = new MainScreen();
                window.setVisible(true);
                dispose();
            }
            else {
                JOptionPane.showMessageDialog(null, "Please enter your username correctly");
            }
        }
    });
    
    btnStartGame.setBounds(150, 102, 117, 29);
    contentPane.add(btnStartGame);
}

By the way, you should try to use layout managers.

Abra
  • 19,142
  • 7
  • 29
  • 41