2010-07-31 65 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

相關問題