I have a JFrame
and, inside this JFrame
there are two JPanel
s. When I press a key, both of them must listen to this key event and act. I want to take all the keyboard events, and deliver them to both of the JPanel
s. Do you know how to do it?
Edit: Since they must do different things, I need two different listeners, sorry for not being specific.
Edit2: I made a simple code to show you the problem. When I press the up key, both of the JPanel
s displayed must change their string; in this code only one of them actually react!
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();
}
}
One of the ways is use methods from SwingUtilities for Java6 (notice SwingUtilities for Java7 have got a few changes, but not important in this case) is possible to redirect, distribute, multiple events that came from Standard Swing Listeners, simple example about redirect mouse events from one container to the another,
Instead of KeyListener
, use Key Bindings and have distinct Action
implementations for each panel. By using the WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
input map, both panels can respond.
Addendum: Because the search ends after finding a valid binding for the key, the example below forwards the event to the elements of a List<MyPanel>
, each of which can respond differently via an available 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<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();
}
});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With