Java 如何在打击时采取行动;输入“;启用时";取消“;JFileChooser中的按钮?
我在Java 如何在打击时采取行动;输入“;启用时";取消“;JFileChooser中的按钮?,java,swing,keyboard,look-and-feel,jfilechooser,Java,Swing,Keyboard,Look And Feel,Jfilechooser,我在JFrame中有一个JFileChooser。我在JFileChooser中添加了一个ActionListener,这样单击时“取消”按钮就可以工作了。我也可以用tab键点击“取消”按钮,但当我点击“回车”键时,什么也没有发生(即,ActionListener不会用事件命令JFileChooser.Cancel\u SELECTION)。我必须如何处理JFileChooser,以便在单击“取消”按钮时按“回车”键相当于单击“取消”按钮 下面是我看到的(错误)行为的一个简单示例: import
JFrame
中有一个JFileChooser
。我在JFileChooser
中添加了一个ActionListener
,这样单击时“取消”按钮就可以工作了。我也可以用tab键点击“取消”按钮,但当我点击“回车”键时,什么也没有发生(即,ActionListener
不会用事件命令JFileChooser.Cancel\u SELECTION
)。我必须如何处理JFileChooser
,以便在单击“取消”按钮时按“回车”键相当于单击“取消”按钮
下面是我看到的(错误)行为的一个简单示例:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
public final class TestApp {
public static void main(final String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
final JFileChooser chooser = new JFileChooser();
chooser.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
System.exit(0);
}
});
final JFrame frame = new JFrame();
frame.add(chooser);
frame.pack();
frame.setVisible(true);
}
catch (final Throwable t) {
t.printStackTrace();
}
}
});
}
}
要查看(mis)行为,请执行程序,单击“取消”,然后按“回车”键。程序不会在我的平台上终止——尽管当我点击“取消”按钮时会终止
扩展JFileChooser
和覆盖cancelSelection()
也不起作用(显然,在“取消”按钮上按下“回车”键时不会调用该函数)
(mis)行为发生在使用Java 5、6和7的Fedora 10 x86_64系统上
附录:以下内容向当前的KeyboardFocusManager
添加了一个keyeventprocessor
,似乎可以执行我想要的操作:
import java.awt.Component;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
public final class TestApp {
public static void main(final String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
final JFileChooser chooser = new JFileChooser();
chooser.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
System.out.println(e.paramString());
System.exit(0);
}
});
final KeyboardFocusManager kfm = KeyboardFocusManager
.getCurrentKeyboardFocusManager();
kfm.addKeyEventPostProcessor(new KeyEventPostProcessor() {
@Override
public boolean postProcessKeyEvent(final KeyEvent e) {
if (e.getID() == KeyEvent.KEY_RELEASED
&& e.getKeyCode() == KeyEvent.VK_ENTER) {
final Component comp = e.getComponent();
if (chooser.isAncestorOf(comp)) {
if (!(comp instanceof JButton)) {
chooser.approveSelection();
}
else {
final JButton button = (JButton) comp;
if ("Cancel".equals(button.getText())) {
chooser.cancelSelection();
}
else {
chooser.approveSelection();
}
}
}
}
return false;
}
});
final JFrame frame = new JFrame();
frame.add(chooser);
frame.pack();
frame.setVisible(true);
}
catch (final Throwable t) {
t.printStackTrace();
}
}
});
}
}
然而,要区分按“取消”按钮上的enter键和其他任何地方,似乎需要做很多工作
你觉得它有什么问题吗
发现的解决方案:将GUI外观设置为我的系统(Linux)的本机外观可以满足我的需要,而不需要其他任何东西。这是我所不知道的,也是我一直在寻找的。解决方案是具备以下条件
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
作为main()
方法的第一个可执行语句。这样就可以省去所有的焦点监听器、关键事件处理器等
我已将100分授予最有帮助的受访者
程序不会在我的平台上终止
我看到MacOSX10.5、Ubuntu10和Windows7上使用(各种)Java5和Java6正常运行。我将您的exit()
替换为println()
,以查看事件:
System.out.println(rootDirChooser.getSelectedFile().getName() + e.paramString());
它可能有助于指定您的平台和版本;如果可能,还应验证安装是否正确
我不确定我是否理解你的目标;但是,作为另一种选择,考虑重写<代码>批准SETIONCE()<代码>:
增编:
目标是使在“取消”按钮上按“回车”键的动作与单击“取消”按钮的动作相同
如中所述,您可以更改与VK\u ENTER
关联的操作
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
InputMap map = chooser.getInputMap(JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
map.put(enter, "cancelSelection");
如果您希望更改仅在“取消”按钮具有焦点时发生,则需要在一段时间内完成
增编:
我找到了一个使用KeyboadFocusManager
的解决方案。你觉得怎么样
我可以看到每种方法的优点和缺点,所以我在下面概述了这两种方法。使用KeyboadFocusManager
查找所有按钮,但不提供独立于区域设置的方法来区分它们;focuslistener
方法只能看到approve按钮,它是特定于用户界面的。不过,您可以将这些方法结合起来以获得更好的结果。第二种意见也不会有问题
增编:
我已经更新了下面的代码,不再需要知道“取消”按钮的本地化名称和使用密钥绑定
import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.plaf.metal.MetalFileChooserUI;
public final class FileChooserKeys
implements ActionListener, FocusListener, PropertyChangeListener {
private final JFileChooser chooser = new JFileChooser();
private final MyChooserUI myUI = new MyChooserUI(chooser);
private final KeyStroke enterKey =
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
private void create() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
chooser.addActionListener(this);
myUI.installUI(chooser);
myUI.getApproveButton(chooser).addFocusListener(this);
KeyboardFocusManager focusManager =
KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(this);
frame.add(chooser);
frame.pack();
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.paramString());
}
@Override
public void focusGained(FocusEvent e) {
System.out.println("ApproveButton gained focus.");
}
@Override
public void focusLost(FocusEvent e) {
System.out.println("ApproveButton lost focus.");
}
@Override
public void propertyChange(PropertyChangeEvent e) {
Object o = e.getNewValue();
InputMap map = chooser.getInputMap(
JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
if (o instanceof JButton) {
if ("focusOwner".equals(e.getPropertyName())) {
JButton b = (JButton) o;
String s = b.getText();
boolean inApproved = b == myUI.getApproveButton(chooser);
if (!(s == null || "".equals(s) || inApproved)) {
map.put(enterKey, "cancelSelection");
} else {
map.put(enterKey, "approveSelection");
}
}
}
}
private static class MyChooserUI extends MetalFileChooserUI {
public MyChooserUI(JFileChooser b) {
super(b);
}
@Override
protected JButton getApproveButton(JFileChooser fc) {
return super.getApproveButton(fc);
}
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new FileChooserKeys().create();
}
});
}
}
如果单击“取消”按钮,则程序将终止。我们的目标是让在“取消”按钮上按“回车”键的动作与单击“取消”按钮的动作完全相同。@史蒂夫·埃默森:Mac OS上的aqua L&F似乎不像其他L&F那样实现文件选择器键绑定。@stacker:VirtualBox使它太容易了,但现在我有三个系统需要修补。:-)@垃圾神根据取消键是否具有焦点来更改与enter键关联的操作似乎有点过分。我找到了一个使用KeyboadFocusManager的解决方案。你觉得怎么样?@Steve Emmerson:我已经回答了上面的问题,但是我没有看到你的
KeyEventPostProcessor
。知道哪个按钮是哪个按钮也有同样的问题。谢谢,我很高兴有机会研究这个有趣的问题。这不是默认的L&F吗?@trashgod默认的L&F取决于OS/JVM的组合:对于Linux或Solaris和Sun的JVM,它是Java(跨平台)L&F;对于Windows/Sun,它是Windows L&F;对于Mac OS/X和Mac的JVM,它是Mac L&F。有关更多信息,请参阅。
import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.plaf.metal.MetalFileChooserUI;
public final class FileChooserKeys
implements ActionListener, FocusListener, PropertyChangeListener {
private final JFileChooser chooser = new JFileChooser();
private final MyChooserUI myUI = new MyChooserUI(chooser);
private final KeyStroke enterKey =
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
private void create() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
chooser.addActionListener(this);
myUI.installUI(chooser);
myUI.getApproveButton(chooser).addFocusListener(this);
KeyboardFocusManager focusManager =
KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(this);
frame.add(chooser);
frame.pack();
frame.setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.paramString());
}
@Override
public void focusGained(FocusEvent e) {
System.out.println("ApproveButton gained focus.");
}
@Override
public void focusLost(FocusEvent e) {
System.out.println("ApproveButton lost focus.");
}
@Override
public void propertyChange(PropertyChangeEvent e) {
Object o = e.getNewValue();
InputMap map = chooser.getInputMap(
JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
if (o instanceof JButton) {
if ("focusOwner".equals(e.getPropertyName())) {
JButton b = (JButton) o;
String s = b.getText();
boolean inApproved = b == myUI.getApproveButton(chooser);
if (!(s == null || "".equals(s) || inApproved)) {
map.put(enterKey, "cancelSelection");
} else {
map.put(enterKey, "approveSelection");
}
}
}
}
private static class MyChooserUI extends MetalFileChooserUI {
public MyChooserUI(JFileChooser b) {
super(b);
}
@Override
protected JButton getApproveButton(JFileChooser fc) {
return super.getApproveButton(fc);
}
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new FileChooserKeys().create();
}
});
}
}