Java 为什么不是';t JDialog触发键侦听器';什么是按键法?

Java 为什么不是';t JDialog触发键侦听器';什么是按键法?,java,swing,keylistener,jdialog,Java,Swing,Keylistener,Jdialog,这是我的密码 JToolBar customizeKeys = new JToolBar(); customizeKeys.add(new ChangeKeyListen("left")); private class ChangeKeyListen extends AbstractAction{ private JDialog myDialog; class KeyGetter extends KeyAdapter { @Override

这是我的密码

 JToolBar customizeKeys = new JToolBar();
 customizeKeys.add(new ChangeKeyListen("left"));
 private class ChangeKeyListen extends AbstractAction{
    private JDialog myDialog;
    class KeyGetter extends KeyAdapter {
        @Override
        public void keyPressed(KeyEvent e) {
            super.keyPressed(e);
            OtherPanel.this.map(
                        KeyEvent.getKeyText(e.getKeyCode()),
                                            keyAction);
            myDialog.setVisible(false);
            myDialog.removeKeyListener(getKeyListeners()[0]);
        }
    };
    public ChangeKeyListen(String name) {
        super(name);
    }
    @Override
    public void actionPerformed(ActionEvent e) {
       myDialog = new JOptionPane().createDialog("Press a key");
       myDialog.setVisible(true);
       myDialog.requestFocusInWindow();
       System.out.println(myDialog.getFocusableWindowState());
       myDialog.addKeyListener(new KeyGetter());
       System.out.println( myDialog.getKeyListeners());
     }
}
我在这里试图做的是,当用户单击添加到JToolBar的带有动作属性的JButton时,用户将收到我自己定制的对话框的提示。然后用户可以按任意键关闭对话框(实际上它只是不可见的)。当我运行应用程序时,一切看起来都很好。JToolBar看起来正确,按钮看起来正确。当我单击按钮时,弹出对话框时会出现正确的控制器行为。(仅可见),但是当我按下一个键时,根本不会触发键适配器的keyPressed方法

我所做的调试工作是首先确保JDialog可以首先聚焦,以便它可以从键盘接收按键事件。我是用这条线做的

System.out.println(myDialog.getFocusableWindowState());
我在控制台上看到的是真的。接下来,我确保设置了关键侦听器。那是我用的

 System.out.println( myDialog.getKeyListeners());
这是打印出来的

[Ljava.awt.event.KeyListener;@350b914b
我假设它是从堆中分配的对象的正确内存地址

然后我检查了类似的线程

我的问题不可能是因为出现了对话框,并且我确保密钥侦听器添加了“打印密钥侦听器”行。 我无法使用用户在中所说的内容,因为我需要监听按键并在稍后的程序中使用该按键。 这也没用 因为我需要对按键的一般反应来确定按下了哪个键

我知道keyPressed没有被执行,因为我在方法和这个print语句中放置了一个断点

   System.out.println(KeyEvent.getKeyText(e.getKeyCode()));  
没有在控制台上打印任何东西


有人知道我如何解决这个问题吗?

您正在将KeyListener添加到由JOptionPane创建的对话框中

但是,重点是对话框上的JButton。KeyEvents只被分派到具有焦点的组件,因此您的密钥侦听器代码永远不会被调用

为什么要尝试侦听任何键来关闭对话框?该程序对用户不友好。用户不知道这是关闭对话框的方法,因为这不是标准的UI约定。用户应单击按钮关闭对话框


如果您确实需要在对话框打开时收听任何按下的按键,请查看以下内容:如何使用
AWTEventListener
收听任何按键事件,而不管哪个组件有焦点。

处理过非常类似的问题,我鼓励那些希望将侦听器添加到JDialog组件的人遵循所示的方法。它允许对组件进行更多控制

下面的示例演示了一个自定义对话框,每当文本使用

public类DialogWithListener扩展JDialog{
私有JTextField textField=新JTextField();
私有布尔userPressedOk=false;
/**
*创建一个对话框,允许用户在文本字段中输入文本。
*
*每次用户按键时,使用
*{@code predsAndMsgs}中的{@link Predicate}。如果文本不满足
*对于所有谓词,该对话框显示与第一个谓词关联的消息
*不满足谓词。
* 
*@param predsAndMsgs
*从{@link Predicate}到我们将向其显示的消息的映射
*如果用户输入的文本不满足谓词,则返回用户
*/
公共对话WithListener(映射predsAndMsgs){
JLabel textfieldlab=新的JLabel(“输入文本:”);
//如果用户输入的文本满足我们的谓词,则显示此选项
String okText=“一切正常”;
JLabel statusLabel=新的JLabel(okText);
对象[]paneContent={textFieldLabel,textField,statusLabel};
JButton-okButton=新JButton(“OK”);
okButton.addActionListener(e->{
userPressedOk=true;
setVisible(假);
});
对象[]选项={okButton};
JOptionPane optionPane=新JOptionPane(paneContent,
JOptionPane.QUESTION_消息,JOptionPane.DEFAULT_选项,null,
选择权);
getContentPane().add(选项窗格);
setLocationRelativeTo(optionPane.getParent());
setFocusTo(文本字段);
//每次释放钥匙时检查用户输入
addKeyListener(新的KeyAdapter(){
@凌驾
公共无效密钥已释放(KeyEvent事件){
验证(predsAndMsgs,textField.getText(),okText,
状态标签,OK按钮);
}
});
setModal(真);
可设置大小(假);
包装();
}
/**
*验证{@code textToValidate}。
*
*{@link predsAndMsgs}中的{@link谓词}确定文本
*有效。如果文本无效,则显示关联的消息
*使用谓词并禁用此对话框的“确定”按钮。
* 
*@param predsAndMsgs
*来自{@link Predicate}的映射,必须为
*{@code textToValidate}添加到我们将向用户显示的消息中
*如果谓词不满足。
*@param textToValidate
*我们根据中的{@link Predicate}验证此文本
*{@link predsAndMsgs}
*@param-okText
*如果{@code textToValidate}满足所有条件,则显示此文本
*谓词
*@param statusLabel
*显示{@link-okText}或
*第一个谓词的消息,对于
*{@link textToValidate}
*@param-okButton
*我们启用和禁用此按钮取决于
*{@link textToValidate}有效
*/
专用void验证(Map predsAndMsgs、,
public class DialogWithListener extends JDialog {
    private JTextField textField = new JTextField();
    private boolean userPressedOk = false;

    /**
     * Creates a dialog that lets the user enter text in a text field.
     * <p>
     * Each time the user presses a key, the text is validated using the
     * {@link Predicate}s in {@code predsAndMsgs}. If the text doesn't satisfy
     * all predicates, the dialog shows the message associated with the first
     * unsatisfied predicate.
     * 
     * @param predsAndMsgs
     *            a map from {@link Predicate}s to the messages we'll show to
     *            users if the text they entered doesn't satisfy the predicates
     */
    public DialogWithListener(Map<Predicate<String>, String> predsAndMsgs) {

        JLabel textFieldLabel = new JLabel("Enter text:");

        // Show this if the text the user entered satisfies our predicates
        String okText = "All good";

        JLabel statusLabel = new JLabel(okText);

        Object[] paneContent = { textFieldLabel, textField, statusLabel };

        JButton okButton = new JButton("OK");
        okButton.addActionListener(e -> {
            userPressedOk = true;
            setVisible(false);
        });

        Object[] options = { okButton };
        JOptionPane optionPane = new JOptionPane(paneContent,
                JOptionPane.QUESTION_MESSAGE, JOptionPane.DEFAULT_OPTION, null,
                options);

        getContentPane().add(optionPane);
        setLocationRelativeTo(optionPane.getParent());

        setFocusTo(textField);

        // Check the user input each time a key is released
        textField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent event) {
                validate(predsAndMsgs, textField.getText(), okText,
                        statusLabel, okButton);
            }
        });

        setModal(true);
        setResizable(false);

        pack();
    }

    /**
     * Validates the {@code textToValidate}.
     * <p>
     * The {@link Predicate}s in {@link predsAndMsgs} determine whether the text
     * is valid. If the text is invalid, we show the message that is associated
     * with the predicate and disable this dialog's OK button.
     * 
     * @param predsAndMsgs
     *            a map from {@link Predicate}s that must hold for the
     *            {@code textToValidate} to the messages we'll show to the user
     *            if a predicate is not satisfied.
     * @param textToValidate
     *            we validate this text against the {@link Predicate}s in
     *            {@link predsAndMsgs}
     * @param okText
     *            this text is shown if the {@code textToValidate} satisfies all
     *            predicates
     * @param statusLabel
     *            a {@link JLabel} that either shows the {@link okText} or the
     *            message of the first predicate that doesn't hold true for the
     *            {@link textToValidate}
     * @param okButton
     *            we enable and disable this button depending on whether the
     *            {@link textToValidate} is valid
     */
    private void validate(Map<Predicate<String>, String> predsAndMsgs,
            String textToValidate, String okText, JLabel statusLabel,
            JButton okButton) {
        // Get the first predicate that the text to validate doesn't satisfy
        Optional<Predicate<String>> unsatisfiedPredMaybe = predsAndMsgs
                .keySet().stream().filter(pred -> !pred.test(textToValidate))
                .findFirst();
        // At least one predicate was not satisfied
        if (unsatisfiedPredMaybe.isPresent()) {
            // Tell the user the text they entered can't be accepted
            String msg = predsAndMsgs.get(unsatisfiedPredMaybe.get());
            statusLabel.setText(msg);
            okButton.setEnabled(false);
        } else {
            statusLabel.setText(okText);
            okButton.setEnabled(true);
        }
        pack();
    }

    private void setFocusTo(JComponent comp) {
        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentShown(ComponentEvent ce) {
                comp.requestFocusInWindow();
            }
        });
    }

    public Optional<String> display() {
        userPressedOk = false;
        // Because the dialog is modal it will block here
        setVisible(true);
        String dialogResult = null;
        if (userPressedOk) {
            dialogResult = textField.getText();
        }
        return Optional.ofNullable(dialogResult);
    }
}
public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager
                        .getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException
                    | IllegalAccessException
                    | UnsupportedLookAndFeelException e) {
                e.printStackTrace();
            }
            createAndShowGUI();
        }
    });
}

private static void createAndShowGUI() {
    JFrame frame = new JFrame();
    JButton showDialogButton = new JButton("Show Dialog");

    // Define the predicates that the user entered-text should satisfy and
    // the messages shown to the user if it doesn't
    Map<Predicate<String>, String> predicatesAndMessages = new HashMap<>();
    Predicate<String> dontMentionHisName = text -> !text
            .contains("Voldemort");
    predicatesAndMessages.put(dontMentionHisName,
            "Sssh! You can't say that!");

    DialogWithListener dialog = new DialogWithListener(
            predicatesAndMessages);
    dialog.setTitle("My dialog");
    showDialogButton.addActionListener(e -> dialog.display().ifPresent(
            userText -> System.out.println(userText)));

    frame.getContentPane().add(showDialogButton);

    frame.pack();
    frame.setVisible(true);
}