按“Enter”键后如何操作当选择“取消”时JFileChooser 中的按钮?
我在 JFrame
中有一个 JFileChooser
。我已将 ActionListener
添加到 JFileChooser
中,以便“取消”按钮在单击时起作用。我还可以按 Tab 键切换到“取消”按钮,但是当我按下“Enter”键时,什么也没有发生(即,事件命令 JFileChooser.CANCEL_SELECTION 不会调用
ActionListener
)。我必须如何处理JFileChooser
,以便在“取消”按钮上按“Enter”键相当于单击“取消”按钮?
这是我看到的(错误)行为的一个简单示例:
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();
}
}
});
}
}
要查看(错误)行为,请执行程序,按 Tab 键切换到“取消”,然后按“Enter”键。该程序不会在我的平台上终止——尽管当我单击“取消”按钮时它会终止。
扩展 JFileChooser
和重写 cancelSelection()
也不起作用(显然,当在“取消”按钮上按下“Enter”键时,不会调用该函数)。
该(错误)行为发生在我使用 Java 5、6 和 7 的 Fedora 10 x86_64 系统上。
附录:以下内容将 KeyEventPostProcessor
添加到当前 KeyboardFocusManager
中,并且似乎执行以下操作我想要什么:
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();
}
}
});
}
}
然而,只是为了区分按下“取消”按钮上的回车键和其他地方的回车键,这似乎需要做很多工作。
您看到它有什么问题吗?
发现的解决方案:将 GUI 外观设置为我的系统 (Linux) 的本机外观即可满足我的要求,无需任何其他操作。这就是我所不知道的,也是我所寻找的。解决方案是将以下内容
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
作为 main()
方法的第一个可执行语句。然后,我们可以省去所有焦点侦听器、关键事件处理器等。
我将 100 分授予最有帮助的受访者。
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.
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).
The (mis)behavior occurs on my Fedora 10 x86_64 system with Java 5, 6, and 7.
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?
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());
as the first executable statement of the main()
method. One can then dispense with all focus listeners, key event processors, etc.
I've awarded the 100 points to the most helpful respondent.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我在使用(不同的)Java 5 和 6 的 Mac OS X 10.5、Ubuntu 10 和 Windows 7 上看到正常操作。我用
println()
替换了您的exit()
来查看事件:可能有助于指定您的平台和版本;如果可能,还请验证安装是否正确。
我不确定我是否理解你的目标;但是,作为替代方案,请考虑覆盖
approveSelection()
:附录:
正如按键绑定中所讨论的,您可以更改与
VK_ENTER
关联的操作。如果您希望仅在“取消”按钮具有焦点时发生更改,则需要在 焦点监听器。
附录:
我可以看到优点和缺点每种方式都有缺点,所以我在下面概述了这两种方式。使用
KeyboadFocusManager
查找所有按钮,但不提供独立于区域设置的方法来区分它们;Focus Listener
方法只能看到批准按钮,并且它是特定于 UI 的。不过,您可以结合使用这些方法以获得更好的结果。第二个意见不会有问题。附录:
我更新了下面的代码,以便无需了解“取消”按钮的本地化名称并使用键绑定。
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()
withprintln()
to see the event:It may help to specify your platform and version; if possible, verify correct installation as well.
I'm not sure I understand your goal; but, as an alternative, consider overriding
approveSelection()
:Addendum:
As discussed in Key Bindings, you can change the action associated with
VK_ENTER
.If you want the change to occur only while the "Cancel" button has focus, you'll need to do it in a Focus Listener.
Addendum:
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; theFocus 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.Addendum:
I've updated the code below to eliminate the need to know the localized name of the "Cancel" button and use key bindings.