The correct way of waiting for strings to become equal
Asked Answered
T

5

0

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.

Tuinal answered 2/12, 2008 at 14:12 Comment(0)
T
5

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.

Teodoro answered 2/12, 2008 at 14:19 Comment(0)
I
6

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.

Indulgent answered 2/12, 2008 at 14:42 Comment(3)
I'd recommend doing "some text".equals(textField.getText()) to prevent a null pointer exception if getText() returns null. Good habit to get into whenever you're comparing a constant to a variable.Gaulin
Ah, thank you for pointing that out! I've edited the answer to take your suggestion into account.Indulgent
I surely use ActionListeners, it's just that the case is beyond trivial ActionListeners (i think). More of a two-way ActionListener ;) with a crazy recursive method supplying UI components. Thanks for your reply though. On my way of refactoring.Tuinal
T
5

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.

Teodoro answered 2/12, 2008 at 14:19 Comment(0)
C
2

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... ;-)

Carpometacarpus answered 2/12, 2008 at 14:18 Comment(0)
M
2

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("");
        }
    }
 }
Mistletoe answered 3/12, 2008 at 3:0 Comment(1)
Desktop.getDesktop().browse( new URI("stackoverflow.com")); sounds so much Java 6 to me. :) Excellent!Tuinal
T
0

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.

Tribromoethanol answered 2/12, 2008 at 14:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.