如何让两个JPanels听同一个事件?

我有一个JFrame ,在这个JFrame有两个JPanel 。 当我按下一个键时,他们都必须听这个关键事件并采取行动。 我想拍摄所有的键盘事件,并将它们传递给两个JPanel 。 你知道怎么做吗?

编辑:因为他们必须做不同的事情,我需要两个不同的听众,抱歉没有具体。

Edit2:我制作了一个简单的代码来向您展示问题。 当我按下向上键时,显示的两个JPanel都必须改变它们的字符串; 在这段代码中,其中只有一个实际上有所反应

 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(); } } 

而不是KeyListener ,使用键绑定,并为每个面板具有不同的Action实现。 通过使用WHEN_ANCESTOR_OF_FOCUSED_COMPONENT输入映射,两个面板都可以响应。

附录:因为搜索在找到密钥的有效绑定后结束,所以下面的示例事件转发List的元素,每个元素都可以通过可用的Action响应不同。

 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 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(); } }); } } 

其中一种方法是使用SwingUtilities for Java6中的方法(注意SwingUtilities for Java7有一些变化,但在这种情况下不重要)可以重定向,分发来自标准Swing Listeners的多个事件, 关于重定向鼠标的简单示例从一个容器到另一个容器的事件 ,

您应该创建一个XXListener实现,并通过.addXXListener将该侦听器添加到您需要的所有组件中。

您可以使用观察者模式。 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);