JOptionPane showMessageDialog - не сфокусировать кнопку «ОК» - PullRequest
0 голосов
/ 27 мая 2019

Я пытаюсь создать 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 Ответ

2 голосов
/ 27 мая 2019

Один способ: создать объект 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);
        }
    }
} 

Чтобы избавиться от действия ввода, необходимо изменить привязки клавиш для клавиши ввода в панели 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);
            }
        }
    }
}

Однако, как только вы приступите к созданию более сложных диалогов, просто пропустите создание JDialogs ивместо этого создайте свой собственный JDialog, один с компонентами, размещенными там, где вы хотите.Сделайте их модальными, если вы хотите, чтобы они остановили приложение, пока не разберетесь.

...