我在自己的框架中将JFileChooser与框架中的其他自定义组件一起嵌入到程序中。这是我的应用程序的设计,因为它可以帮助可视化我的问题:

如果您不知道,JFrame标题正下方的列表就是JFileChoosers。这种方法的工作方式是将快捷方式分配给目标,然后按这些快捷键时,所选文件将移动到目标。

我这样做的策略是将快捷方式分配给整个框架的javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOWInputMap范围。

但是令人讨厌的是,某些东西(我假设是JFileChooser)不断响应/吸收我不希望的按键。例如,如果我按Ctrl+C,则我的快捷方式操作不会运行。我已经尝试使用 native 的外观(我使用的是Windows 7)和默认的L&F来解决此问题,并且两种情况都存在相同的问题。我认为它可能正在尝试对JFileChooser中的选定文件执行复制操作,因为如果我单击其中一个按钮以使其失去焦点,我的Ctrl+C命令突然就会执行我的操作。

但是,我不太确定JFileChooser是如何做到的。当我在上面调用getKeyListeners()时,它返回一个空数组。我还尝试在所有三个范围内清除此键组合的输入映射,但它似乎仍在吸收按键。

谁能给我一些使JFileChooser忽略Ctrl+C的示例代码?另外,如果有人可以告诉我将来如何调试此类问题,也会很有帮助。

这是到目前为止我尝试过的一些代码。您还可以使用它来尝试自己进行测试,因为此代码可以按原样编译和运行:

package com.sandbox;

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

public class Sandbox {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("control C"), "println");
        panel.getActionMap().put("println", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("The JPanel action was performed!");
            }
        });

        panel.add(buildFileChooser());  //if you comment out this line, Ctrl+C does a println, otherwise my action is ignored.

        frame.setContentPane(panel);

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    private static JFileChooser buildFileChooser() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.getActionMap().clear(); //I've tried lots of ideas like this, but the JFileChooser still responds to Ctrl+C
        return fileChooser;
    }
}

更新:我已经尽力递归地清除inputMaps并删除了JFileChooser及其所有子组件的keyListeners,而JFileChooser 仍然吞下了我的Ctrl + C命令。这是我用来执行此操作的代码(我将JFileChooser传递给了它):
private static void removeKeyboardReactors(JComponent root) {
    System.out.println("I'm going to clear the inputMap of: " + root);
    root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).clear();
    root.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).clear();
    root.getInputMap(JComponent.WHEN_FOCUSED).clear();
    root.getActionMap().clear();

    if (root.getRootPane() != null) {
        removeKeyboardReactors(root.getRootPane());
    }

    for (KeyListener keyListener : root.getKeyListeners()) {
        root.removeKeyListener(keyListener);
    }

    for (Component component : root.getComponents()) {
        if (component instanceof JComponent) {
            removeKeyboardReactors((JComponent) component);
        } else if (component instanceof Container) {
            Container container = (Container) component;
            for (Component containerComponent : container.getComponents()) {
                if (containerComponent instanceof JComponent) {
                    removeKeyboardReactors((JComponent) containerComponent);
                } else {
                    System.out.println("This Container Component was not a JComponent: " + containerComponent);
                }
            }
        } else {
            System.out.println("This was not a JComponent: " + component);
        }
    }
}

最佳答案



我怀疑详细信息 View 和 ListView 之间的区别在于,一个使用JTable,另一个使用JList。因此,我猜您只需要从详细信息 View 的JTable中删除绑定(bind)即可。

无需创建详细信息面板即可完成此操作:

InputMap im = (InputMap)UIManager.get("Table.ancestorInputMap");
KeyStroke ctrlC = KeyStroke.getKeyStroke("control C");
//im.put(ctrlC, "none");
im.remove(ctrlC);

同样,应该注意的是,此解决方案(以及您当前拥有的解决方案)将删除所有组件的默认Ctrl + C功能,而不仅仅是为JFileChooser实例化的组件。

编辑:



您的代码使用getParent()方法获取包含绑定(bind)的InputMap。该InputMap由组件的所有实例共享。使用以下组件时,组件将仅具有唯一绑定(bind):
component.getInputMap(...).put(...);

即,将绑定(bind)添加到组件InputMap,而不是其父级InputMap。



参见UIManager Defaults。此列表列出了给定LAF的默认值。我不知道这是否是正确的事情。据我所知,效果与您现在使用的代码相同。这只是另一种方法,或者从InputMap删除绑定(bind)而无需实际组件访问父InputMap。

第二编辑:

一些简单的代码来显示InputMap是相同的:
public static void main(String[] args)
{
    JButton first = new JButton("button");
    System.out.println(first.getInputMap().getParent());

    InputMap im = (InputMap) UIManager.get("Button.focusInputMap");
    System.out.println(im);
}

关于java - 如何删除JFileChooser上的Ctrl + C Action ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16229526/

10-14 02:56