6

This problem is solved.

I'm am developing a Java Swing based projected, and the look & feel of the application is completely customized. We are trying to maintain a consistent appearance throughout the program, and the default Java dialog windows are not the same.

The current issue requires a control blocking call to the user prompt. Similar to JOptionPane.showConfirmDialog() In this case, the static call produces a window, and halts the flow of the program until the user selects an option. It also returns the value of the option. Note that the GUI itself is not locked up logically, but the user cannot interact with the rest of it.

int n = JOptionPane.showConfirmDialog(this,
    "Are you sure?",
    "Confirm"
    JOptionPane.YES_NO_OPTION);

I would like to duplicate this functionality with a customized appearance, and using a string. Ideally, my code would appear as follows:

String result = CustomPrompt.showPrompt(this,
    "Please enter your name", //Text
    "Prompt.",                //Title
    "John Smith");            //Default

This will generally be used for password input, and I understand the return type of a password is different, but this is an example. This can be accomplished by using a series of button and event listeners, in several classes, but the readability of the code and reliability of the application diminishes.

The Frame would be built via NetBeans and customized from there. I do understand that such a prompt already exists in Swing, but it's look & feel is completely and entirely different.

The question summarized: How to use a customized frame to prompt the user for input in a blocking manner.

The solution to this problem is as follows:

public class PromptForm extends JDialog
{
    transient char[] result;

    public char[] getResult()
    {
        return result;
    }
    public PromptForm(Frame parent)
    {
        super(parent, true);
        initComponents();
    }
    public void prompt()
    {
        this.setVisible(true);
    }
    public static char[] promptForPassword(Frame parent)
    {
        PromptForm pf = new PromptForm(parent);
        pf.prompt();
        return pf.getResult();
    }
    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt)
    {
        result = jPasswordField1.getPassword();
        setVisible(false);
        dispose();
    }
    private void initComponents() {...}

    private javax.swing.JButton jButton1;
    private javax.swing.JPasswordField jPasswordField1;
}

Called by:

    char [] ret = PromptForm.promptForPassword(this);
    JOptionPane.showMessageDialog(this, new String(ret), "Neat", JOptionPane.QUESTION_MESSAGE);
trashgod
  • 196,350
  • 25
  • 213
  • 918
Reivax
  • 127
  • 2
  • 9
  • You know that you can give any JComponent (actually any Object, but most Objects won't work the way you want it to) as a parameter? Give `this` as a parent (like you do in your example), and the rest of the GUI should 'lock' up. – Hidde Feb 01 '12 at 16:28
  • Obviously you're doing some custom painting, not using a custom LaF. – mre Feb 01 '12 at 16:33
  • 1
    Yes that's correct, it's not actually loading a true LookAndFeel, but assigning properties to each component via Netbeans. Regardless of good operating procedure, these are the rules I must follow, set down from on high. – Reivax Feb 01 '12 at 16:36
  • @Reivax, Thank you for the confirmation! – mre Feb 01 '12 at 16:39

1 Answers1

5

Make CustomPrompt extends JDialog, have it's constructor call super passing the owner Window and the desired ModalityType.

public class CustomPrompt extends JDialog {

  public static String showPrompt(Window parent, String title, String text, 
         String defaultText) {
    final CustomPrompt prompt = new CustomPrompt(parent);
    prompt.setTitle(title);
    // set other components text
    prompt.setVisible(true);

    return prompt.textField.getText();
  }

  private JTextField textField;

  // private if you only want this prompt to be accessible via constructor methods
  private CustomPrompt(Window parent) {
    super(parent, Dialog.DEFAULT_MODALITY_TYPE); 
    // Java >= 6, else user super(Frame, true) or super(Dialog, true);
    initComponents(); // like Netbeans
  }

  // initComponents() and irrelevant code. 
}
Anthony Accioly
  • 19,883
  • 7
  • 62
  • 102
  • Thanks, modal is what nailed it. Much appreciated. My solution: Create a PromptForm class extending JDialog. Constructor signature: public PromptForm(Frame parent) { super(parent, true); initComponents();} – Reivax Feb 01 '12 at 16:51