2

背景:我有一个表格单元格编辑器,调用时会弹出一个对话框,其中包含复选框列表和 2 个按钮(确定和取消)。一切正常。我后来注册了键盘操作,以便 ENTER 和 ESCAPE 键可以执行确定/取消操作。仍然没有问题。

使用相同的技术,我尝试注册 SPACE 键以执行第三个操作。这没有火。示例代码:

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class DialogTest implements Runnable
{
  JDialog dialog;
  JList jlist;

  public static void main(String[] args)
  {
    SwingUtilities.invokeLater(new DialogTest());
  }

  public void run()
  {    
    ActionListener okListener = new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        close(true);
      }
    };

    ActionListener cancelListener = new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        close(false);
      }
    };

    ActionListener otherListener = new ActionListener()
    {
      public void actionPerformed(ActionEvent e)
      {
        doOther();
      }
    };

    JButton okButton = new JButton("OK");
    okButton.addActionListener(okListener);

    JButton cancelButton = new JButton("Cancel");
    cancelButton.addActionListener(cancelListener);

    jlist = new JList(new String[]{"A", "B", "C", "D", "E", "F", "G"});
    jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    jlist.setVisibleRowCount(5);

    JScrollPane scroll = new JScrollPane(jlist);
    scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

    JPanel buttonsPanel = new JPanel(new FlowLayout());
    buttonsPanel.add(okButton);
    buttonsPanel.add(cancelButton);

    JPanel content = new JPanel(new BorderLayout());
    content.add(scroll, BorderLayout.CENTER);
    content.add(buttonsPanel, BorderLayout.SOUTH);

    dialog = new JDialog((Frame) null, true);
    dialog.setContentPane(content);
    dialog.pack();
    dialog.setLocationRelativeTo(null);

    dialog.getRootPane().registerKeyboardAction(okListener,
        KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
        JComponent.WHEN_IN_FOCUSED_WINDOW);

    dialog.getRootPane().registerKeyboardAction(cancelListener,
        KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
        JComponent.WHEN_IN_FOCUSED_WINDOW);

    // This doesn't work
    dialog.getRootPane().registerKeyboardAction(otherListener,
        KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
        JComponent.WHEN_IN_FOCUSED_WINDOW);

    dialog.setVisible(true);
  }

  private void close(boolean commit)
  {
    if (commit)
    {
      System.out.println("Now saving...");
    }
    else
    {
      System.out.println("Now closing...");
      System.exit(0);
    }
  }

  private void doOther()
  {
    System.out.println("current selection: " + jlist.getSelectedValue());
  }
}

编辑

感谢 mKorbel 的建议(和有用的链接!),我得到了这个工作:

1)将行更改ActionListener otherListener = new ActionListener(){...}为:

Action otherListener = new AbstractAction(){...}

2)将SPACE击键注册更改为:

KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0);
Object key = keyStroke.toString();
jlist.getInputMap().put(keyStroke, key);
jlist.getActionMap().put(key, otherAction);

请注意,注册是针对 JList 的,而不是针对其他 2 个击键的 JDialog。

4

1 回答 1

2

很难对陛下说什么菜刀......

编辑

我忘记了 SPACE 已将 KeyBindings 注册为人类 JButtons 加速器(鼠标、ENTER 和 SPACE),如果选择了 JButton,则可能存在并发

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class DialogTest implements Runnable {

    private JDialog dialog;
    private JList jlist;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new DialogTest());
    }

    @Override
    public void run() {
        ActionListener okListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                close(true);
            }
        };

        ActionListener cancelListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                close(false);
            }
        };

        ActionListener otherListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                doOther();
            }
        };
        JButton okButton = new JButton("OK");
        okButton.addActionListener(okListener);
        JButton cancelButton = new JButton("Cancel");
        cancelButton.addActionListener(cancelListener);
        jlist = new JList(new String[]{"A", "B", "C", "D", "E", "F", "G"});
        jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        jlist.setVisibleRowCount(5);
        JScrollPane scroll = new JScrollPane(jlist);
        scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        JPanel buttonsPanel = new JPanel(new FlowLayout());
        buttonsPanel.add(okButton);
        buttonsPanel.add(cancelButton);
        JPanel content = new JPanel(new BorderLayout());
        content.add(scroll, BorderLayout.CENTER);
        content.add(buttonsPanel, BorderLayout.SOUTH);
        dialog = new JDialog((Frame) null, true);
        dialog.setContentPane(content);
        dialog.pack();
        dialog.setLocationRelativeTo(null);
        dialog.getRootPane().registerKeyboardAction(okListener,
                KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

        dialog.getRootPane().registerKeyboardAction(cancelListener,
                KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        // This doesn't work
        /*dialog.getRootPane().registerKeyboardAction(otherListener,
        KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0),
        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);*/
        dialog.getRootPane().getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "doSomething");
        dialog.getRootPane().getActionMap().put("doSomething", new AbstractAction() {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        dialog.setVisible(true);
    }

    private void close(boolean commit) {
        if (commit) {
            System.out.println("Now saving...");
        } else {
            System.out.println("Now closing...");
            System.exit(0);
        }
    }

    private void doOther() {
        System.out.println("current selection: " + jlist.getSelectedValue());
    }
}
于 2012-11-29T16:50:35.517 回答