問題描述
我在 JFrame
中有一個 JFileChooser
.我在 JFileChooser
中添加了一個 ActionListener
,以便單擊取消"按鈕時可以使用.我也可以選擇取消"按鈕,但是當我按下Enter"鍵時,什么也沒有發生(即,ActionListener
沒有被事件命令 JFileChooser.CANCEL_SELECTION 調用代碼>).我必須對
JFileChooser
做什么,以便在取消"按鈕上按Enter"鍵相當于單擊取消"按鈕?
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();
}
}
});
}
}
要查看(錯誤)行為,請執行程序,使用 Tab 鍵選擇取消",然后按Enter"鍵.該程序不會在我的平臺上終止——盡管當我單擊取消"按鈕時它會終止.
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()
也不起作用(顯然,當在取消"按鈕).
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).
(錯誤)行為發生在我的 Fedora 10 x86_64 系統上,使用 Java 5、6 和 7.
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 正常運行.我用 println()
exit()> 觀看活動:
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());
}
}
附錄:
目標是讓在取消"按鈕上按Enter"鍵的操作與單擊取消"按鈕的操作相同.
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.
如 鍵綁定中所述a>,您可以更改與 VK_ENTER
關聯的操作.
As discussed in Key Bindings, you can change the action associated with VK_ENTER
.
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
InputMap map = chooser.getInputMap(JFileChooser.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
map.put(enter, "cancelSelection");
如果您希望僅在取消"按鈕具有焦點時發生更改,您需要在 焦點監聽器.
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
的解決方案.你怎么看?
I found a solution that uses
KeyboadFocusManager
, instead. What do you think?
我可以看到優點&各方面的缺點,所以我在下面概述了兩者.使用 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();
}
});
}
}
這篇關于如何在點擊“Enter"時采取行動在“取消"時JFileChooser 中的按鈕?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!