2012-04-16 14 views
4

問題の説明:このJFrameの内部には、ボタン付きのJPanelがあります。ボタンを押すと、アクションリスナーが変更します。現在のJPanelには、他の2つのJPanelを含む新しいJPanelがあります。これら2つのJPanelには、ユーザーが "up"キーを押したときに両方で何かを作成するinputMapがあります。問題は、私が新しいものでJPanelを変更したときに、 "up"キーが何もしないことです。JFrameのパネルを変更する新しいパネルのinputMapを無効にする

コードは次のとおりです:SSCCEですので、コピーして貼り付けてください。

この変更されたコードは、私が時々前に解決した別の質問から来ています。 How to make two JPanels listen to the same event? (コードは私が選択した回答に含まれています)。

import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.util.Arrays; 
import java.util.List; 
import javax.swing.AbstractAction; 
import javax.swing.Action; 
import javax.swing.BorderFactory; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 

public class TwoPanelsTest extends JFrame { 

private static MyPanel one = new MyPanel("One"); 
private static MyPanel two = new MyPanel("Two"); 
private static List<MyPanel> list = Arrays.asList(one, two); 
private PanelsController panelsController; 

public TwoPanelsTest() { 
    super("TwoPanelsTest"); 
    panelsController= new PanelsController(this); 
    this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
    this.setSize(400,400); 
    this.setLocationRelativeTo(null); 
    this.setVisible(true); 
} 

private static class MyPanel extends JPanel { 

    private String string = " will be updated though its action."; 
    private Action action = new UpdateAction(this); 
    private String name; 
    private JLabel label; 

    public MyPanel(String name) { 
     this.name = name; 
     this.label = new JLabel(name + string, JLabel.CENTER); 
     this.setLayout(new GridLayout()); 
     this.setFocusable(true); 
     this.add(label); 
    } 

    public Action getAction() { 
     return action; 
    } 

    private void update() { 
     label.setText(name + ": " + System.nanoTime()); 
    } 

    private static class UpdateAction extends AbstractAction { 

     private MyPanel panel; 

     public UpdateAction(MyPanel panel) { 
      this.panel = panel; 
     } 

     @Override 
     public void actionPerformed(ActionEvent ae) { 
      panel.update(); 
     } 
    } 
}//MyPanel 

private static class ButtonPanel extends JPanel{ 
    private JButton button ; 
    private PanelsController panelsController; 

    public ButtonPanel(PanelsController panelsController){ 
     this.panelsController=panelsController; 

     button = new JButton("Button"); 
     button.setActionCommand("buttonPressed"); 
     button.addActionListener(this.panelsController); 
     this.setFocusable(true); 
     add(button); 
    } 
}//ButtonPanel 

private static class PanelsController implements ActionListener { 

    private TwoPanelsTest twoPanelsTest; 

    public PanelsController(TwoPanelsTest twoPanelsTest){ 
     this.twoPanelsTest=twoPanelsTest; 
     this.twoPanelsTest.getContentPane().add(new ButtonPanel(this)); 
    } 

    @Override 
    public void actionPerformed(ActionEvent ae) { 
     if (ae.getActionCommand().equals("buttonPressed")){ 
      twoPanelsTest.getContentPane().removeAll(); 
      twoPanelsTest.getContentPane().invalidate(); 

      JPanel panel = new JPanel(new GridLayout(0, 1, 10, 10)); 
      panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 
      panel.add(one); 
      panel.add(two); 
      panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) 
      .put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up"); 
      panel.getActionMap().put("up", new AbstractAction() { 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        for (MyPanel panel : list) { 
         panel.getAction().actionPerformed(e); 
        } 
       } 
      }); 
      twoPanelsTest.getContentPane().add(panel); 
      twoPanelsTest.validate(); 
      twoPanelsTest.repaint(); 
     } 
    }//ActionPerformed 

}//PanelsController 

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

     @Override 
     public void run() { 
      TwoPanelsTest t = new TwoPanelsTest(); 
     } 
    }); 
} 
} 
+3

'ためCardLayout'、[例](http://stackoverflow.com/a/を使用しないのはなぜ:ところで

は、また、Javaアプリケーションウィンドウ内のグローバルホットキーを聴くための別の方法があります5655843/230513)? – trashgod

+0

問題が解決するかどうかわかりませんが、私はそれを最後のチャンスとしたいと考えていました。私がCardlayoutで理解できるものから、removeAll()/ add()よりも多くのメモリが無駄になります。私は重度のJPanelsを使用する予定なので、CardLayoutはプログラムのパフォーマンスに影響を与える可能性があります。ちなみに、mgarinは私に解決策を与えました、とにかくありがとう。 – AR89

答えて

4

まあ、その非常に簡単 - あなたは内部の任意のコンポーネントなしでこれら二つのパネルを持っており、それらはホットキーの使用を聴きたい場合は:

panel.getInputMap (JComponent.WHEN_IN_FOCUSED_WINDOW) 
    .put (KeyStroke.getKeyStroke (KeyEvent.VK_UP, 0), "up"); 

JComponent.WHEN_IN_FOCUSED_WINDOWの代わりJComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT。

それ以外の場合は、キーイベントを捕捉できるように、パネル内に何かを集中させる必要があります。

Toolkit.getDefaultToolkit().addAWTEventListener (new AWTEventListener() 
{ 
    public void eventDispatched (AWTEvent event) 
    { 
     // All application key events will be passed here 
    } 
}, AWTEvent.KEY_EVENT_MASK); 
+0

あなたの提案はうまくいきます、あなたが言ったようにIputMapを変更しました。私はこのAWTEventListenerを見ていきます。初めて見ます。ありがとうございました。 – AR89

+0

+1の 'AWTEventListener'; more [here](http://stackoverflow.com/a/1374430/230513)。 – trashgod

関連する問題