Search code examples
javaswingjoptionpane

Java showInputDialog select custom text


I have rename dialog for rename file

String renameTo = JOptionPane.showInputDialog(gui, "New Name", currentFile.getName());

it works this way, but I have a problem. the problem is that I set the default value with the extension of the file but I just want the file name to be selected.

sample : my file name = yusuf.png

I want select only yusuf like;

like this


Solution

  • There is a lot going on inside JOptionPane, it's one of the things that makes it so powerful, it also makes it a little inflexible to.

    Two immediate problems are apparent...

    1. You can't gain direct access to the JTextField been used to get input from the user
    2. The JOptionPane wants to control which components have focus when the dialog is first shown.

    Setting up the JTextField is actually straight forward...

    String text = "yusuf.png";
    int endIndex = text.lastIndexOf(".");
    
    JTextField field = new JTextField(text, 20);
    if (endIndex > 0) {
        field.setSelectionStart(0);
        field.setSelectionEnd(endIndex);
    } else {
        field.selectAll();
    }
    

    This will basically select all the text from the start of the String up to the last . or all the text if no . can be found.

    The difficult part now is taking back focus control from the JOptionPane

    // Make a basic JOptionPane instance
    JOptionPane pane = new JOptionPane(field, 
            JOptionPane.PLAIN_MESSAGE, 
            JOptionPane.OK_CANCEL_OPTION, 
            null);
    // Use it's own dialog creation process, it's simpler this way
    JDialog dialog = pane.createDialog("Rename");
    // When the window is displayed, we want to "steal"
    // focus from what the `JOptionPane` has set
    // and apply it to our text field
    dialog.addWindowListener(new WindowAdapter() {
        @Override
        public void windowActivated(WindowEvent e) {
            // Set a small "delayed" action
            // to occur at some point in the future...
            // This way we can circumvent the JOptionPane's
            // focus control
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    field.requestFocusInWindow();
                }
            });
        }
    });
    // Put it on the screen...
    dialog.setVisible(true);
    dialog.dispose();
    // Get the resulting action (what button was activated)
    Object value = pane.getValue();
    if (value instanceof Integer) {
        int result = (int)value;
        // OK was actioned, get the new name
        if (result == JOptionPane.OK_OPTION) {
            String newName = field.getText();
            System.out.println("newName = " + newName);
        }
    }
    

    And, crossing our fingers, we end up with something looking like...

    Example

    Personally, I'd wrap this up in a nice reusable class/method call which returned the new text or null based on the action of the user, but that's me

    Isn't there an easier way?

    Of course, I just like showing you the most difficult solution possible ... 😳 (sarcasm) ... it's kind of why I suggested wrapping it up in it's own utility class, so you can re-use it later 😉