In a Swing app a method should continue only after user enters a correct answer. The correct answer is stored in a String with user answer being set by a listener to another String. So, the code is
while (!correctAnswer.equals(currentAnswer)) {
// wait for user to click the button with the correct answer typed into the textfield
}
// and then continue
Is everything fine with this approach or would you somehow refactor it? Doesn't it impose extra penalty on CPU?
Here's a somewhat similar question.
Are you new to UI programming? The reason I ask is that your answer is predicated on a procedural style of coding, which isn't what UIs are about. It tends to be event-driven.
In this case the solution is pretty easy: add an event listener (ActionListener) to the submit button and check the result there. If its OK, go on. If not, say so and let them try again.
As others have suggested, you'll want to use assign a listener to the button, which will be called when the button is pressed.
Here's a incomplete example illustrating how to use an ActionListener
and implementing its actionPerformed
method which is called when the button is pressed:
...
final JTextField textField = new JTextField();
final JButton okButton = new JButton("OK");
okButton.addActionListner(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
if ("some text".equals(textField.getText()))
System.out.println("Yes, text matches.");
else
System.out.println("No, text does not match.");
}
});
...
You may just want to implement ActionListener
in the class where the button and text field resides, so you don't need to declare the two objects as final
. (I just used an anonymous inner class to keep the example short.)
For more information, you may want to take a look at How to Write an Action Listener from The Java Tutorials.
Also, for general information on how events work in Java, the Lesson: Writing Event Listeners from The Java Tutorials may be useful.
Edit: Changed the expression inside if
statement from textField.getText().equals("some text")
to "some text".equals(textField.getText())
in order to prevent a NullPointerException
if textField
was null
, per suggestion from Mr. Shiny and New's comment.
I don't think I get the logic there, but it reminds me of old Basic times... :-) I don't see why the application forces the user to type something already known (unless it is a password or something).
You write the typing is observed by a listener. So why not do the test there? Don't do a loop waiting for an event, let Java do it (and other stuff). If necessary, break your logic in two, and go to the second part when you detect the correct input is given in the listener.
I hope this makes sense... ;-)
Yes, as everyone said here.
For a gui app the best way to handle user input is to wait for an event to be fired.
Then a method could be used to validate the input and if succeed you can continue with the flow, that could be go to another page.
Here's a complete ( yet simple ) example of a login screen, that validates the user input and if succeed performs some action.
This code has no other value than show in a complete ready to run sample how this concept is applied.
simple gui http://img229.imageshack.us/img229/1532/simplenz0.png
// * used for brevity. Preffer single class per import
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.net.*;
import java.io.*;
public class MatchString{
private final JTextField password;
private final JFrame frame;
public static void main( String [] args ){
MatchString.show();
}
public static void show(){
SwingUtilities.invokeLater( new Runnable(){
public void run(){
new MatchString();
}
});
}
private MatchString(){
password = new JPasswordField( 20 );
frame = new JFrame("Go to www.stackoverflow");
init();
frame.pack();
frame.setVisible( true );
}
private void init(){
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( new JPanel(){{
add( new JLabel("Password:"));
add( password );
}});
// This is the key of this question.
// the password textfield is added an
// action listener
// When the user press enter, the method
// validatePassword() is invoked.
password.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ) {
validatePassword();
}
});
}
private void validatePassword(){
// If the two strings match
// then continue with the flow
// in this case, open SO site.
if ( "stackoverflow".equals(password.getText())) try {
Desktop.getDesktop().browse( new URI("http://stackoverflow.com"));
frame.dispose();
} catch ( IOException ioe ){
showError( ioe.getMessage() );
} catch ( URISyntaxException use ){
showError( use.getMessage() );
} else {
// If didn't match.. clear the text.
password.setText("");
}
}
}
If your strings are coming from a human user at GUI rates, there's very little point in optimizing for performance. The human won't be able to enter more than perhaps one to three strings per second, and that's nothing for the machine.
In this particular case, where you need to do stuff to get an input to test, I would suggest using a do-while
loop.