1

I am trying to create showMessageDialog that will have ONLY ONE button (i.e. OK). I want that button to be un-focused. That means when the dialog opens, is user clicks on Enter key, the dialog should not close. Use must have to click on 'OK' button then only the dialog should disappear.

But I am getting now is always the 'OK' button is focused. So when the dialog popup, and user doesn't see and press Enter key, the dialog closes.

Why I need this: This is not an error message. Only informational message that user must need to see before proceeding. And in this case the big monitors are a little far away from the users location. I have written code to make a sound when the dialog shows up, but user may not listen and hits Enter key. So I want user to see the dialog and clicks on OK button

Sample Code:

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;


import java.awt.Color;
import java.awt.Font;

public class MessageDialogInFrame extends JFrame{

    public MessageDialogInFrame() {
        getContentPane().setBackground(Color.DARK_GRAY);
        setTitle("Message Dialog in Frame");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        setResizable(false);
        setSize(400, 300);
        getContentPane().setLayout(null);
    }

    public static void main(String[] args){
        ImageIcon icon = new ImageIcon("src/images/turtle64.png");
        JTextArea commentTextArea = new JTextArea("Hello", 10, 50);
        commentTextArea.setBackground(Color.YELLOW);
        Font font = new java.awt.Font("Dialog", 0, 15);
        commentTextArea.setFont(font);
        commentTextArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(commentTextArea);
        scrollPane.setBackground(Color.YELLOW);       

        JOptionPane.showMessageDialog(new MessageDialogInFrame(), 
                "I appear as part of the frame!!", "Customized Dialog", 
                JOptionPane.INFORMATION_MESSAGE, icon);
    }
}

Original Code:

private static int showColoredDialog(int category, Component parentComp, String message, String title, int optionType, int messageType, Color color) {
    JTextArea commentTextArea = new JTextArea(message, 10, 50);
    commentTextArea.setBackground(color);
    commentTextArea.setFont(UiFactory.getInfo().getLabelFont());
    commentTextArea.setEditable(false);
    JScrollPane scrollPane = new JScrollPane(commentTextArea);
    scrollPane.setBackground(color);

    switch (category) {
    case 0:
        JOptionPane.showMessageDialog(parentComp, scrollPane, title, messageType);
        return 0;
    case 1:
        return JOptionPane.showConfirmDialog(parentComp, scrollPane, title, optionType, messageType);
    }
    return -1;
}

SOLUTION:

int result = JOptionPane.CLOSED_OPTION;
final JOptionPane pane = new JOptionPane(scrollPane, JOptionPane.WARNING_MESSAGE, JOptionPane.OK_OPTION, null, new String[] {"OK"});
            JDialog dialog = pane.createDialog(null, title);
            commentTextArea.requestFocus();
            dialog.setVisible(true);
            if (pane.getValue() != null) result = JOptionPane.OK_OPTION;
            return result;

enter image description here

SK.
  • 1,390
  • 2
  • 28
  • 59

2 Answers2

2

One way: create a JOptionPane object via its constructor, recursively search its component tree for the JButton, and make it non-focusable:

JOptionPane optionPane = new JOptionPane();
optionPane.setMessage("Fubars Rule!");
optionPane.setMessageType(JOptionPane.PLAIN_MESSAGE);
optionPane.setOptionType(JOptionPane.DEFAULT_OPTION);
recursiveUnfocusButtons(optionPane);
JDialog dialog = optionPane.createDialog(null, "Option Title");
dialog.setVisible(true); 
System.exit(0);

and the magic sauce:

private static void recursiveUnfocusButtons(Component component) {
    if (component instanceof JButton) {
        component.setFocusable(false);
        return;
    } else if (component instanceof Container) {
        for (Component c : ((Container) component).getComponents()) {
            recursiveUnfocusButtons(c);
        }
    }
} 

To get rid of the enter action, you need to change the key bindings for the enter key in the JOptionPane:

import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class JOptionNoFocus {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JOptionPane optionPane = new JOptionPane();
            optionPane.setMessage("Fubars Rule!");
            optionPane.setMessageType(JOptionPane.PLAIN_MESSAGE);
            optionPane.setOptionType(JOptionPane.DEFAULT_OPTION);

            KeyStroke enterStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
            optionPane.getInputMap(JComponent.WHEN_FOCUSED).put(enterStroke, enterStroke.toString());
            optionPane.getActionMap().put(enterStroke.toString(), new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // do nothing
                }
            });

            recursiveUnfocusButtons(optionPane);
            JDialog dialog = optionPane.createDialog(null, "Option Title");
            dialog.setVisible(true); 
            System.exit(0);
        });
    }

    private static void recursiveUnfocusButtons(Component component) {
        if (component instanceof JButton) {
            JButton button = (JButton) component;
            button.setFocusable(false);
            return;
        } else if (component instanceof Container) {
            for (Component c : ((Container) component).getComponents()) {
                recursiveUnfocusButtons(c);
            }
        }
    }
}

Once you get into creating more complex dialogs though, just skip creating JDialogs and instead create your own JDialog, one with components placed where you desire. Make them modal if you want them to stop the application until dealt with.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • The OK button is not highlighted, but when I press Enter key the dialog closes – SK. May 27 '19 at 15:45
  • @SK. this will require changing keybindings – Hovercraft Full Of Eels May 27 '19 at 15:56
  • Thanks a lot for your time. Yes, the default OK button works. I have up-voted. Is there a way to do it using showMessageDialog instaed of createDialog. The reason I am asking is we have a textarea in the dialog. I am posting our original code in my question – SK. May 27 '19 at 18:31
  • @SK.: You can create a JPanel and put it into a JOptionPane, but once you start doing this, the easiest thing to do is to skip using JOptionPanes and go right to creating a JDialog. – Hovercraft Full Of Eels May 27 '19 at 19:01
  • found another simpler way. Added the code in my original question – SK. May 29 '19 at 15:33
0

So, there is a thing in JOptionClass called showOptionDialog(); One of its constructor looks like this: JOptionPane.showOptionDialog(Component com, String message, String title, int optType, int msgType, Icon icon, Object[] options, Object initialValue);

As you can see whe can give to its constructor an array that will represent the buttons on the panel.

Code looks like this

Still

Hovered over