2012-11-26 3 views
3

Action을받는 JButton 클래스를 만들었습니다. JButton 클래스에는 키 스트로크 & 마우스 리스너가 포함되어 있으므로 필요한만큼 여러 클래스에서 같은 클래스를 사용할 수 있습니다.JButton & Action & KeyBinding

내 문제는 : JButton은 키를 누를 때 포커스를 얻지는 않지만 동작을 수행합니다. 새로운 배경이나 버튼이 액션을 수행했다는 것을 사용자에게 알리는 것을 만들어야합니다.

어떤 아이디어 ?? 당신은 단순히 해당 인스턴스에 KeyBinding의를 추가 할 수 있습니다 때

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Insets; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.Action; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.KeyStroke; 
import javax.swing.SwingConstants; 
import javax.swing.border.LineBorder; 
import swtdesigner.SwingResourceManager; 

public class IButtonSave extends JButton{ 
    private static final long serialVersionUID = 1L; 
    private Action action = null; 
    public IButtonSave() { 
     super(); 
     setFocusPainted(true); 
     setFocusable(true); 

     try { 
      jbInit(); 
     } catch (Throwable e) { 
      e.printStackTrace(); 
     } 
    } 

    private void jbInit() throws Exception { 
     setMargin(new Insets(0, 0, 0, 0)); 
     setBorder(new LineBorder(Color.black, 1, true)); 
     setIconTextGap(0); 
     setHorizontalTextPosition(SwingConstants.CENTER); 
     setVerticalTextPosition(SwingConstants.TOP); 
     setPreferredSize(new Dimension(50, 43)); 
     setMinimumSize(new Dimension(50, 43)); 
     setMaximumSize(new Dimension(50, 43)); 
     addMouseListener(new ThisMouseListener()); 
     setVerifyInputWhenFocusTarget(true); 
    } 

    public void setAction(Action a){ 
     action = a; 
     KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F1,0,true); 
     KeyStroke ks2 = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0); 
     getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "Save"); 
     getInputMap(JComponent.WHEN_FOCUSED).put(ks2, "Save"); 

     getActionMap().put("Save", a); 
     setText("Save [F1]"); 
     setIcon(SwingResourceManager.getIcon(SwingResourceManager.class, "/images/small/save.png")); 
     setToolTipText("[F1]"); 
    } 

    private class ThisMouseListener extends MouseAdapter { 
     public void mouseClicked(MouseEvent e) { 
      this_mouseClicked(e); 
     } 
    } 
    protected void this_mouseClicked(MouseEvent e) { 
     if(e.getClickCount() >= 1){ 
      action.actionPerformed(null); 
     } 
    } 
} 
+0

'super.setAction'을 호출하지 않는 이유는 무엇입니까? –

+0

아니, 당신의 방식으로 그것을 호출하는 아무 문제가 없다, 버튼은 잘 작동하지만 키 F1을 누르면 작업이 완료되지만 초점은 절대로 버튼으로 이동하지 않습니다. 내가해야 할 일은 버튼을 집중시키고 동작이 수행 될 때 누르는 것입니다. – Motasem

+0

더 나은 도움을 더 빨리 얻으려면 [SSCCE] (http://sscce.org/)를 게시하십시오 (이 예제는 옵션 창에 'IButtonSave'를 표시하기 위해 적어도 main (String [])이 필요합니다) . –

답변

5

JButton 클래스를 확장 : 여기

내 코드?

당신이 원하는 무엇인지 그러나 이것은 나를 위해 잘 작동하지 않기 :

기본적으로

(마우스 클릭으로 활성화 또는 F1을 누르면 할 수있는 JButton 한 초점 창에 있고 누를 경우 이동합니다으로 초점은 JButton) 또는 ENTER (초점이 JButton 인 경우에만).

AbstractAction이는 (따라서 나는 당신이 원하는 생각되는 버튼의 이득에 초점을 다할 것 F1를 눌러) JButtonrequestFocusInWindow()를 호출 호출 될 때 :

enter image description here

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JTextField; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 

public class Test { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

       final JButton btn = new JButton("Button"); 

       AbstractAction aa = new AbstractAction() { 
        @Override 
        public void actionPerformed(ActionEvent ae) { 
         System.out.println("Here"); 

         btn.requestFocusInWindow();//request that the button has focus 
        } 
       }; 

       //so button can be pressed using F1 and ENTER 
       btn.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter"); 
       btn.getActionMap().put("Enter", aa); 
       btn.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), "F1"); 
       btn.getActionMap().put("F1", aa); 

       btn.addActionListener(aa);//so button can be clicked 

       JTextField tf = new JTextField("added to show ENTER wont work unless button in focus"); 

       frame.add(tf); 
       frame.add(btn, BorderLayout.SOUTH); 

       frame.pack(); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 

UPADTE :

@GuillaumePolet suggested (+1 그에게) JButtonprocessKeyBinding을 무시하고 해당 키를 확인하고 이상 호출 방법 :

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JTextField; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 

public class Test { 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       final JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

       final JButton btn = new JButton("Button") { 
        @Override 
        protected boolean processKeyBinding(KeyStroke ks, KeyEvent ke, int i, boolean bln) { 
         boolean b = super.processKeyBinding(ks, ke, i, bln); 

         if (b && ks.getKeyCode() == KeyEvent.VK_F1) { 
          requestFocusInWindow(); 
         } 

         return b; 
        } 
       }; 

       AbstractAction aa = new AbstractAction() { 
        @Override 
        public void actionPerformed(ActionEvent ae) { 
         System.out.println("Here"); 
        } 
       }; 

       //so button can be pressed using F1 and ENTER 
       btn.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter"); 
       btn.getActionMap().put("Enter", aa); 
       btn.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), "F1"); 
       btn.getActionMap().put("F1", aa); 

       btn.addActionListener(aa);//so button can be clicked 

       JTextField tf = new JTextField("added to show ENTER wont work unless button in focus"); 

       frame.add(tf); 
       frame.add(btn, BorderLayout.SOUTH); 

       frame.pack(); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 
+0

니모닉은 L & F mouseless 수정 자 (일반적으로 Alt 키)와 결합해야합니다.또한이 작업을 수동으로 처리하는 대신 JButton에서 직접 설정하거나 ActionListener –

+0

을 사용하면 100 % 정확하지만 F1 키를 누르면 – Motasem

+0

@Motasem에 포커스가 지정되지 않습니다. requestFocusInWindow()'버튼 인스턴스 –

3

수 없음이 그것을 할 수있는 최선의 방법인지를하지만 상당히 충분히 작동하고 가장 좋은 방법이 아닌 경우, 이 대답에서 무료 SSCCE을 얻을 수 있습니다.

나는 processKeyBindings()를 오버라이드하고 true를 반환하면 포커스가 수행되었음을 나타냅니다. 다른 것을하고 싶다면 코드를 수정해야합니다.

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 

import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.KeyStroke; 
import javax.swing.SwingUtilities; 

public class IButtonSave extends JButton { 
    private static final long serialVersionUID = 1L; 

    public IButtonSave() { 
     super(); 
     setFocusPainted(true); 
     setFocusable(true); 
    } 

    @Override 
    protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { 
     boolean processKeyBinding = super.processKeyBinding(ks, e, condition, pressed); 
     if (processKeyBinding) { 
      requestFocusInWindow(); 
     } 
     return processKeyBinding; 
    } 

    @Override 
    public void setAction(Action a) { 
     super.setAction(a); 
     KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0, true); 
     KeyStroke ks2 = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); 
     getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "Save"); 
     getInputMap(JComponent.WHEN_FOCUSED).put(ks2, "Save"); 
     getActionMap().put("Save", a); 
     setText("Save [F1]"); 
     setToolTipText("[F1]"); 
    } 

    protected void initUI() { 
     JFrame frame = new JFrame(IButtonSave.class.getSimpleName()); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JTextArea textarea = new JTextArea(5, 30); 
     JPanel buttonPanel = new JPanel(); 
     AbstractAction someAction = new AbstractAction() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       System.err.println("Action performed"); 
      } 
     }; 
     IButtonSave button = new IButtonSave(); 
     button.setAction(someAction); 
     buttonPanel.add(button); 
     frame.add(new JScrollPane(textarea)); 
     frame.add(buttonPanel, BorderLayout.SOUTH); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new IButtonSave().initUI(); 
      } 
     }); 
    } 

} 
+0

+1 processKeyBinding의 오버라이드 –

+0

Thaaaaaaaaaanks, 정말 도움이됩니다. – Motasem