我嵌入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;
}
}
更新 :据递归清除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);
}
}
}
细节来看仍会有一个人口稠密的InputMap
我怀疑差的详细信息视图和列表视图是一个使用JTable中其他一个JList。 所以我猜你只需要的细节来看,从JTable中删除绑定。
这可以在不产生细节面板来完成:
InputMap im = (InputMap)UIManager.get("Table.ancestorInputMap");
KeyStroke ctrlC = KeyStroke.getKeyStroke("control C");
//im.put(ctrlC, "none");
im.remove(ctrlC);
此外,应该注意的是,该解决方案(与您目前拥有的解决方案一起)将删除默认为Ctrl + C功能的所有组件,而不仅仅是实例对JFileChooser的人。
编辑:
难道不应该只从那些我从删除它移除?
您的代码使用的getParent()方法来获取包含绑定的InputMap。 此InputMap由组件的所有实例共享。 当你使用一个组件将只具有独特的绑定:
component.getInputMap(...).put(...);
也就是说,绑定添加到组件的InputMap,而不是其父母的InputMap。
你怎么知道你能做到这一点,这是做正确的事
见UIManager的默认值 。 该列表的默认值给出LAF。 我不知道这是否是正确的事情。 据我所知,效果是一样的,你现在使用的代码。 这又是另一种或删除从InputMap中的绑定,而无需实际组件来访问父母的InputMap。
第二个编辑:
一些简单的代码来显示InputMaps是相同的:
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);
}
显然InputMaps可以有父母。 所以,你的所有内置密钥“反应堆”的清洗还没有完全完成。 正如你可能已经猜到,秋千注册某些组件本身的某些默认键盘绑定。 在Windows上,通常包括按Ctrl + C,因为这是用于将数据复制到剪贴板中的OS标准热键。
此修改removeKeyboardReactors
获取的System.out.println出现对我来说:
private static void removeKeyboardReactors(JComponent root) {
System.out.println("I'm going to clear the inputMap of: " + root);
clearInputMap(root.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT));
clearInputMap(root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW));
clearInputMap(root.getInputMap(JComponent.WHEN_FOCUSED));
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);
}
}
}
private static void clearInputMap(InputMap inputMap) {
inputMap.clear();
while ((inputMap = inputMap.getParent()) != null) {
inputMap.clear();
}
}
我不得不删除此代码removeKeyboardReactors
,因为它是导致堆栈溢出:
if (root.getRootPane() != null) {
removeKeyboardReactors(root.getRootPane());
}
下的整个改性沙盒类如下。 希望这是足以让你对你的方式。 如果你想在键绑定去除更关键的特异性,看一看的InputMap#删除(的KeyStroke) 。
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!");
}
});
JFileChooser fileChooser = buildFileChooser();
panel.add(fileChooser); //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();
removeKeyboardReactors(fileChooser);
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;
}
private static void clearInputMap(InputMap inputMap)
{
inputMap.clear();
while ((inputMap = inputMap.getParent()) != null)
{
inputMap.clear();
}
}
private static void removeKeyboardReactors(JComponent root) {
System.out.println("I'm going to clear the inputMap of: " + root);
clearInputMap(root.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT));
clearInputMap(root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW));
clearInputMap(root.getInputMap(JComponent.WHEN_FOCUSED));
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);
}
}
}
}