JOptionPane showMessageDialog-取消焦点“确定”按钮

时间:2019-05-27 15:23:29

标签: java swing messagedialog

我正在尝试创建仅具有一个按钮的showMessageDialog(即确定)。我希望该按钮不集中。这意味着当对话框打开时,如果用户单击Enter键,则对话框不应关闭。使用必须点击“确定”按钮,然后只有对话框会消失。

但是我现在总是将“确定”按钮对准焦点。因此,当对话框弹出时,用户看不到并按Enter键时,对话框将关闭。

为什么我需要这个:这不是错误消息。用户在继续操作之前仅需要查看的参考消息。在这种情况下,大型显示器离用户位置有点远。我已经编写了在对话框出现时发出声音的代码,但是用户可能听不到并按Enter键。因此,我希望用户看到对话框并单击“确定”按钮

示例代码:

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

原始代码:

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;
}

解决方案:

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

1 个答案:

答案 0 :(得分:1)

一种方法:通过其构造函数创建JOptionPane对象,递归地在其组件树中搜索JButton,并使它不可聚焦:

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

和魔术酱:

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

要摆脱Enter操作,您需要在JOptionPane中更改Enter键的键绑定:

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

但是,一旦您要创建更复杂的对话框,只需跳过创建JDialogs的步骤,而是创建自己的JDialog,将其放置在所需位置的组件即可。如果希望他们在处理之前停止应用程序,请将它们设为模态。