打击“输入”时如何采取行动何时开启“取消” JFileChooser中的按钮? [英] How to act upon hitting "Enter" when on "Cancel" button in JFileChooser?
问题描述
我在 JFrame
中有 JFileChooser
。我已将 ActionListener
添加到 JFileChooser
,以便点击时取消按钮有效。我也可以选中取消按钮,但是当我按下Enter键时,没有任何反应(即,没有使用事件命令调用 ActionListener
JFileChooser.CANCEL_SELECTION
)。我必须对 JFileChooser
做什么才能在取消按钮上点击回车键相当于点击取消按钮?
I have a JFileChooser
in a JFrame
. I've added an ActionListener
to the JFileChooser
so that the "Cancel" button works when clicked. I can also tab to the "Cancel" button, but when I then hit the "Enter" key, nothing happens (i.e., the ActionListener
isn't called with the event command JFileChooser.CANCEL_SELECTION
). What must I do with the JFileChooser
so that hitting the "Enter" key when on the "Cancel" button is equivalent to clicking on the "Cancel" button?
以下是我所看到的(错误)行为的一个简单示例:
Here's a simple example of the (mis)behavior I'm seeing:
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();
}
}
});
}
}
要查看(错误)行为,请执行程序,选项卡取消,然后单击确定键。该程序不会在我的平台上终止 - 虽然我点击取消按钮时会这样做。
To see the (mis)behavior, execute the program, tab to "Cancel", and then hit the "Enter" key. The program doesn't terminate on my platform -- although it does when I click on the "Cancel" button.
扩展 JFileChooser
并覆盖 cancelSelection()
也不起作用(显然,在取消时按Enter键时不调用该函数按钮)。
Extending JFileChooser
and overriding cancelSelection()
also doesn't work (apparently, that function isn't called when the "Enter" key is hit while on the "Cancel" button).
在使用Java 5,6和7的Fedora 10 x86_64系统上发生(误)行为。
The (mis)behavior occurs on my Fedora 10 x86_64 system with Java 5, 6, and 7.
ADDENDUM:以下内容将 KeyEventPostProcessor
添加到当前的 KeyboardFocusManager
,并且似乎按我的意愿执行:
ADDENDUM: The following adds a KeyEventPostProcessor
to the current KeyboardFocusManager
and appears to do what I want:
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();
}
}
});
}
}
然而,这看似很多工作能够区分点击取消按钮上的输入键与其他任何地方的输入键。
It seems like a lot of work, however, just to be able to distinguish between hitting the enter key on the "Cancel" button versus anywhere else.
你觉得它有什么问题吗?
Do you see any problems with it?
发现解决方案:将GUI外观设置为我的系统(Linux)的原生内容,无需任何其他操作即可实现我想要的功能。这就是我所不知道的以及我在寻找的东西。解决方案是具有以下内容
DISCOVERED SOLUTION: Setting the GUI Look and Feel to the native one for my system (Linux) does what I want without the need for anything else. This is what I was ignorant of and what I was looking for. The solution is to have the following
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
作为 main()的第一个可执行语句
方法。然后可以免除所有焦点听众,关键事件处理器等。
as the first executable statement of the main()
method. One can then dispense with all focus listeners, key event processors, etc.
我已经向最有帮助的受访者颁发了100分。
I've awarded the 100 points to the most helpful respondent.
推荐答案
程序不会在我的平台上终止。
The program doesn't terminate on my platform.
我看到Mac OS X 10.5,Ubuntu 10和Windows 7上的正常操作使用(各种)Java 5和6.我替换了你的 exit()
使用 println()
查看事件:
I see normal operation on Mac OS X 10.5, Ubuntu 10 and Windows 7 using (variously) Java 5 and 6. I replaced your exit()
with println()
to see the event:
System.out.println(rootDirChooser.getSelectedFile().getName() + e.paramString());
指定平台和版本可能会有所帮助;如果可能的话,也要验证安装是否正确。
It may help to specify your platform and version; if possible, verify correct installation as well.
我不确定我理解你的目标;但是,作为替代方案,请考虑覆盖 approveSelection()
:
I'm not sure I understand your goal; but, as an alternative, consider overriding approveSelection()
:
private static class MyChooser extends JFileChooser {
@Override
public void approveSelection() {
super.approveSelection();
System.out.println(this.getSelectedFile().getName());
}
}
附录:
目标是在取消按钮上点击回车键的操作与单击取消按钮相同。
The goal is to have the action of hitting the "Enter" key while on the "Cancel" button be identical to clicking on the "Cancel" button.
如 密钥绑定 ,您可以更改与 VK_ENTER
相关联的操作。
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
InputMap map = chooser.getInputMap(JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
map.put(enter, "cancelSelection");
如果您希望仅在取消按钮具有焦点时才进行更改,则需要在 Focus Listener 中进行此操作。
If you want the change to occur only while the "Cancel" button has focus, you'll need to do it in a Focus Listener.
附录:
我找到了一个使用的解决方案
KeyboadFocusManager
,相反。您怎么看?
我可以看到专业人士各方面都有所不同,所以我在下面列出了两个方面。使用 KeyboadFocusManager
查找所有按钮,但不提供区别设置,以区分它们; Focus Listener
方法只能看到批准按钮,并且它是特定于UI的。您仍然可以将这些方法结合起来以获得更好的结果第二种意见不会出现问题。
I can see pros & cons each way, so I've outlined both below. Using KeyboadFocusManager
finds all buttons, but offers no locale independent way to distinguish among them; the Focus Listener
approach can only see the approve button, and it's UI specific. Still, you might combine the approaches for better results. A second opinion wouldn't be out of order.
附录:
我已更新下面的代码无需知道取消按钮的本地化名称并使用键绑定。
I've updated the code below to eliminate the need to know the localized name of the "Cancel" button and use key bindings.
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();
}
});
}
}
这篇关于打击“输入”时如何采取行动何时开启“取消” JFileChooser中的按钮?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!