2010-07-31 40 views
1

我有一个JFileChooserJFrame。我已将ActionListener添加到JFileChooser,以便点击时取消按钮。我也可以选择“取消”按钮,但是当我点击“Enter”键时,没有任何事情发生(即ActionListener未使用事件命令JFileChooser.CANCEL_SELECTION调用)。我该如何处理JFileChooser,以便在“取消”按钮上点击“Enter”键相当于点击“取消”按钮?如何在JFileChooser中的“取消”按钮时点击“Enter”?

这里的(MIS)的一个简单的例子行为我看到:

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()也不起作用(很显然,当在“取消”按钮时按下“Enter”键时,该功能不会被调用)。

我的Fedora 10 x86_64的系统上发生与Java 5,6(MIS)的行为,和7

附录:下面增加了一个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分给了最有帮助的回答者。

+0

谢谢,我很欣赏有机会研究这个有趣的问题。这不是默认的L&F吗? – trashgod 2010-08-06 00:29:08

+0

@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。有关更多信息,请参阅。 – 2010-08-06 18:50:45

回答

3

该程序不会在我的平台上终止。

我看到Mac OS X上正常运行10.5,Ubuntu的10和Windows 7中使用(不同)的Java 5和6我换成你exit()println()看到事件:

System.out.println(rootDirChooser.getSelectedFile().getName() + e.paramString()); 

它可能帮助指定您的平台和版本;如果可能,请验证是否正确安装。

我不知道我理解你的目标;但是,作为一种替代,是重写approveSelection()

private static class MyChooser extends JFileChooser { 

    @Override 
    public void approveSelection() { 
     super.approveSelection(); 
     System.out.println(this.getSelectedFile().getName()); 
    } 
} 

附录:

的目标是有打“回车”键,“取消”的操作按钮是相同的点击在“取消”按钮上。

Key Bindings中所述,您可以更改与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

附录:

我发现,使用KeyboadFocusManager的解决方案,来代替。你怎么看?

我可以看到专业人士&每种方式,所以我在下面概述。使用KeyboadFocusManager找到所有按钮,但不提供区域独立的方式来区分它们; Focus Listener方法只能看到批准按钮,并且它是特定于用户界面的。不过,您可以将这些方法结合起来以获得更好的结果第二个意见不会是无序的。

附录:

我已经更新了下面的代码,以消除需要知道的“取消”按钮的本地化名称,并使用键绑定。

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(); 
      } 
     }); 
    } 
} 
+0

如果您点击“取消”按钮,程序将终止。目标是在“取消”按钮上点击“Enter”键的操作与点击“取消”按钮时的操作相同。 – 2010-08-02 18:26:45

+0

@Steve Emmerson:Mac OS上的Aqua L&F似乎没有像其他L&F一样实现文件选择器键绑定。 – trashgod 2010-08-03 02:46:08

+1

+1在Mac OS X 10.5,Ubuntu 10和Windows 7上测试 – stacker 2010-08-03 06:17:19

相关问题