2011-09-15 148 views
2

在每個窗口/面板中,我都將Enter鍵映射爲defaultButton(意思是即使按下的按鈕沒有對焦,按下Enter鍵也會觸發按鈕按下)。我需要做的是將退出鍵映射到另一個按鍵,這也會觸發第二個按鍵,而不管焦點如何。對於回車鍵的代碼是:如何將「默認按鈕」功能添加到Swing中的兩個按鈕?

// We get the button 
IButton iButton = (IButton)actionToolbar.getComponent(actionToolbar.getComponentCount() - 1); 
// We get the window 
Window window = SwingUtilities.getWindowAncestor(this); 
// Only these two types of windows should have this behaviour 
if (window instanceof JFrame) { 
    ((JFrame)window).getRootPane().setDefaultButton(iButton); 
} 
else if (window instanceof JDialog) { 
    ((JDialog)window).getRootPane().setDefaultButton(iButton); 
} 

現在我需要的是基本相同的代碼,但不斷變化與逃生輸入,或添加一個監聽器....東西,我不能確定什麼。

編輯:我必須在Java 1.4中做到這一點,我知道如果我立即說出它會很好。 (的SwingX項目)

+0

可能使用'鍵Listeners'來解決這個問題。 –

+0

想到了它並嘗試將它們映射到窗口/ rootPane,但它不起作用。可能只是我做錯了什麼。 – Andrija

+2

@哈里noooooo - 忘記keyListeners存在;-) – kleopatra

回答

1

我設法通過增加一個按鍵偵聽器,打開面板,這樣

InputMap iMap = theTaskWindow.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
    iMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape"); 
    ActionMap aMap = theTaskWindow.getRootPane().getActionMap(); 
    aMap.put("escape", new AbstractAction() { 
     private static final long serialVersionUID = 1L; 
     public void actionPerformed(ActionEvent e){ 
     doCancel(); 
     } 
    }); 
4

JXRootPane默認有它,你可以這樣做

private void installKeyboardActions() { 
    Action escAction = new AbstractAction() { 
     @Override 
     public void actionPerformed(ActionEvent evt) { 
      JButton cancelButton = getCancelButton(); 
      if (cancelButton != null) { 
       cancelButton.doClick(20); 
      } 
     } 

     /** 
     * Overridden to hack around #566-swing: 
     * JXRootPane eats escape keystrokes from datepicker popup. 
     * Disable action if there is no cancel button.<p> 
     * 
     * That's basically what RootPaneUI does - only not in 
     * the parameterless isEnabled, but in the one that passes 
     * in the sender (available in UIAction only). We can't test 
     * nor compare against core behaviour, UIAction has 
     * sun package scope. <p> 
     * 
     * Cont'd (Issue #1358-swingx: popup menus not closed) 
     * The extended hack is inspired by Rob Camick's 
     * <a href="http://tips4java.wordpress.com/2010/10/17/escape-key-and-dialog/"> Blog </a> 
     * and consists in checking if the the rootpane has a popup's actionMap "inserted". 
     * NOTE: this does not work if the popup or any of its children is focusOwner. 
     */ 
     @Override 
     public boolean isEnabled() { 
      Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 
      if (component instanceof JComponent) { 
       Action cancelPopup = ((JComponent)component).getActionMap().get("cancel"); 
       if (cancelPopup != null) return false; 
      } 
      return (cancelButton != null) && (cancelButton.isEnabled()); 
     } 
    }; 
    getActionMap().put("esc-action", escAction); 
    InputMap im = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 
    KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); 
    im.put(key, "esc-action"); 
} 


/** 
* Sets the <code>cancelButton</code> property, 
* which determines the current default cancel button for this <code>JRootPane</code>. 
* The cancel button is the button which will be activated 
* when a UI-defined activation event (typically the <b>ESC</b> key) 
* occurs in the root pane regardless of whether or not the button 
* has keyboard focus (unless there is another component within 
* the root pane which consumes the activation event, 
* such as a <code>JTextPane</code>). 
* For default activation to work, the button must be an enabled 
* descendant of the root pane when activation occurs. 
* To remove a cancel button from this root pane, set this 
* property to <code>null</code>. 
* 
* @param cancelButton the <code>JButton</code> which is to be the cancel button 
* @see #getCancelButton() 
* 
* @beaninfo 
* description: The button activated by default for cancel actions in this root pane 
*/ 
public void setCancelButton(JButton cancelButton) { 
    JButton old = this.cancelButton; 

    if (old != cancelButton) { 
     this.cancelButton = cancelButton; 

     if (old != null) { 
      old.repaint(); 
     } 
     if (cancelButton != null) { 
      cancelButton.repaint(); 
     } 
    } 

    firePropertyChange("cancelButton", old, cancelButton);   
} 

/** 
* Returns the value of the <code>cancelButton</code> property. 
* @return the <code>JButton</code> which is currently the default cancel button 
* @see #setCancelButton 
*/ 
public JButton getCancelButton() { 
    return cancelButton; 
} 
+0

不錯,我的加號之一+1 – mKorbel

+0

不幸的是,我不能使用swingx或像@Override之類的東西,因爲必須使用Java 1.4。 – Andrija

+0

@Andrija - 這是我複製源代碼的原因之一:-)鍵綁定自1.3(我認爲)所以,只需繼承JRootPane的子類,就可以編譯代碼並移除編譯器所抱怨的部分。然後子類JFrame創建增強的rootpane並在您的應用程序中隨處使用 – kleopatra

-1

該做的:

window.getContentPane().registerKeyboardAction(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
      onCancel(); 
     } 
    }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 

你的第二個JButton的也應該調用onCancel()點擊時。所以無論是按逃生或點擊這兩個都會做同樣的事情。

+0

-1否,那是嚴重過時的api – kleopatra

1

或其他和非常簡單的方式

import java.awt.*; 
import java.awt.event.ActionEvent; 
import javax.swing.*; 

public class ExampleKeyStrokes { 

    private JFrame frame = new JFrame(); 
    private JButton button; 

    public ExampleKeyStrokes() { 
     button = new JButton(new AbstractAction(" push ENTER ") { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       System.exit(0); 
      } 
     }); 
     button.setText(" Please push ENTER "); 
     //button.setPreferredSize(new Dimension(200, 50)); 
     frame.add(button); 
     frame.getRootPane().setDefaultButton(button); 
     frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("F2"), "clickButton"); 
     frame.getRootPane().getActionMap().put("clickButton", new AbstractAction() { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       button.doClick(); 
      } 
     }); 
     frame.setLocation(150, 150); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
     setFocusButton(); 
    } 

    private void setFocusButton() { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       button.grabFocus(); 
       button.requestFocus(); 
       button.requestFocusInWindow(); 
      } 
     }); 
    } 

    static public void main(String[] s) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       ExampleKeyStrokes eKS = new ExampleKeyStrokes(); 
      } 
     }); 
    } 
} 
+2

做的。不。使用。 setXXSize。 – kleopatra

+0

JButton無法返回preferredSize,如果沒有setText && Font,我無法做到這一點,我們在談論JComponents如何返回它的PreferredSize,:-)'non-PreferredSize Polizistin' :-)我會改變 – mKorbel

相關問題