Dan*_*lan 8 java swing key-events jfilechooser key-bindings
我JFileChooser
在我自己的框架中嵌入了一个框架中的其他自定义组件.这是我的应用程序的设计,因为它可能有助于可视化我的问题:
如果你不能说,JFrame
标题下面的列表是JFileChoosers
.这应该是有效的方法是您为目标分配快捷方式,然后当您按下这些快捷键时,所选文件将移动到目标.
我这样做的策略是将快捷方式分配给一个javax.swing.JComponent.WHEN_IN_FOCUSED_WINDOW
范围InputMap
的整个框架.
但令人讨厌的是,某些东西(我假设JFileChooser
)继续响应/吸收我不想要的按键.例如,如果我按下Ctrl+C
我的快捷键操作则不会运行.我尝试了本机外观(我使用的是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;
}
}
Run Code Online (Sandbox Code Playgroud)
更新:我已经走到递归清除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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
详细信息视图仍将有一个填充的输入映射
我怀疑详细信息视图和列表视图之间的区别在于,一个使用 JTable,另一个使用 JList。所以我猜您只需要从详细信息视图的 JTable 中删除绑定即可。
这可以在不创建详细信息面板的情况下完成:
InputMap im = (InputMap)UIManager.get("Table.ancestorInputMap");
KeyStroke ctrlC = KeyStroke.getKeyStroke("control C");
//im.put(ctrlC, "none");
im.remove(ctrlC);
Run Code Online (Sandbox Code Playgroud)
再次,应该注意的是,此解决方案(以及您当前拥有的解决方案)将删除所有组件的默认 Ctrl+C 功能,而不仅仅是为 JFileChooser 实例化的组件。
编辑:
难道它不应该只从我从中删除它的人中删除它吗?
您的代码使用 getParent() 方法来获取包含绑定的 InputMap。该InputMap 由组件的所有实例共享。当您使用以下内容时,组件将仅具有唯一的绑定:
component.getInputMap(...).put(...);
Run Code Online (Sandbox Code Playgroud)
也就是说,绑定被添加到组件InputMap,而不是其父级InputMap。
您怎么知道您可以做到这一点并且这是正确的做法
请参阅UIManager 默认值。这列出了给定 LAF 的默认值。我不知道这样做是否正确。据我所知效果和你现在使用的代码是一样的。这只是从 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);
}
Run Code Online (Sandbox Code Playgroud)