2012-04-04 6 views
3

私はJFrameを持っていて、このJFrameの中に2つあります。私がキーを押すと、両方の人はこのキーイベントを聞いて行動しなければなりません。私はすべてのキーボードイベントを受け取り、JPanelの両方にそれらを配信したいと思います。あなたはそれをする方法を知っていますか?2つのJPanelを同じイベントで聴くには?

編集:彼らは異なることをしなければならないので、私は2人の異なるリスナーを必要とします。

Edit2:私はあなたに問題を示す簡単なコードを作った。アップキーを押すと、表示されているJPanelの両方が文字列を変更する必要があります。このコードでは、実際に反応するのは1つだけです!

import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 

/** 
* 
* @author antonioruffolo 
*/ 
public class TwoPanelsTest extends JFrame { 

public TwoPanelsTest() { 

    setDefaultCloseOperation(EXIT_ON_CLOSE); 
    setResizable(false); 
    setSize(800, 600); 

    PanelTest panelTest1= new PanelTest(); 
    PanelTest panelTest2= new PanelTest(); 

    GridBagLayout layout= new GridBagLayout(); 
    this.setLayout(layout); 

    GridBagConstraints c = new GridBagConstraints(); 

    c.ipadx = 220; 
    c.ipady = 390; 
    c.insets.right= 0; 
    c.insets.left=30; 
    layout.setConstraints(panelTest1, c); 
    this.add(panelTest1); 

    layout.setConstraints(panelTest2, c); 
    c.ipadx = 220; 
    c.ipady = 390; 
    c.insets.right=250; 
    c.insets.left=50; 
    this.add(panelTest2); 


    setVisible(true); 
    setLocationRelativeTo(null); 
    setTitle("Test"); 
    setFocusable(false); 
} 

private class PanelTest extends JPanel{ 

    private String string="I'm not called by the event"; 
    private InputMap inputmap; 
    private ActionMap actionmap; 

    public PanelTest(){ 
     setFocusable(false); 
     setDoubleBuffered(true); 

     this.setBackground(Color.WHITE); 
     inputmap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); 
     inputmap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "up"); 
     actionmap = getActionMap(); 
     actionmap.put("up", new ActionController(this)); 
    } 

    public void setString(String string){ 
     this.string=string; 
    } 

    @Override 
    public void paintComponent(Graphics g){ 
     super.paintComponent(g); 

     Font infoFont= new Font("OCR A Std", Font.BOLD, 10); 
     g.setFont(infoFont); 
     g.drawString(string, 10, 50); 
    } 
}//PanelTest 

private class ActionController extends AbstractAction{ 

    private PanelTest panel; 

    public ActionController (PanelTest panel){ 
     this.panel=panel; 
    } 

    @Override 
    public void actionPerformed(ActionEvent ae) { 
     panel.setString("Action performed"); 
     panel.repaint(); 
    } 

} 

public static void main(String[] args) { 
    TwoPanelsTest t = new TwoPanelsTest(); 
} 
} 

答えて

5

KeyListenerの代わりに、Key Bindingsを使用して、各パネルに対して別々のActionの実装を使用してください。 WHEN_ANCESTOR_OF_FOCUSED_COMPONENT入力マップを使用すると、両方のパネルが応答できます。

補遺:検索キーのための有効なバインディングを見つけた後に終了するので、転送利用可能Actionを経由して異なる反応をすることができ、それぞれがList<MyPanel>の要素にイベント下の例。

import java.awt.EventQueue; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
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.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 

/** @see http://stackoverflow.com/q/10011564/230513 */ 
public class TwoPanelsTest extends JFrame { 

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

    public TwoPanelsTest() { 
     super("TwoPanelsTest"); 
     this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     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); 
       } 
      } 
     }); 
     this.add(panel); 
     this.pack(); 
     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(); 
      } 
     } 
    } 

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

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

私はKeyBindingsを使用する方が良いことを知っています。私は自分の問題を記述する簡単なコードを投稿しました。 "up"キーを押すと、両方とも表示された文字列を変更する必要がありますが、実際にそれらのうちの1人だけが行います!あなたの入力マップがこのケースに適切でないため、JComponent.WHEN_IN_FOCUSED_WINDOWを使用しました(変更した場合、動作しないことがわかります) – AR89

+0

@ AR89:あなたが意味するものを見ています。上記の例を追加しました。 – trashgod

+0

本当にありがとう、あなたの例は正常に動作し、私はテンプレートとしてそれを使用します! – AR89

1

あなたはXXListener実装を作成し、必要なすべてのコンポーネントに.addXXListenerによってそのリスナーを追加する必要があります。

+0

このアプローチは[ 'EventListenerListを'](http://docs.oracle.com/javase/6/docs/api/javax/swing/event/EventListenerList.html)に概説されています。 – trashgod

1

このためにオブザーバーパターンを使用できます。方法の http://en.wikipedia.org/wiki/Observer_pattern

MyKeyEventListener listener = new MyKeyEventListener(); 
JPanel one = new JPanel(); 
one.addKeyListener(listener);//method might be wrong 
JPanel two = new JPanel(); 
two.addKeyListener(listener); 
listener.addObserver(one); 
listener.addObserver(two); 
関連する問題