Java 如何让两个JPanel监听同一事件?
我有一个Java 如何让两个JPanel监听同一事件?,java,swing,Java,Swing,我有一个JFrame,在这个JFrame里面有两个JPanels。当我按下一个键时,他们两个都必须听这个键事件并采取行动。我想获取所有键盘事件,并将它们传递给JPanels。你知道怎么做吗 编辑:因为他们必须做不同的事情,我需要两个不同的听众,抱歉没有具体说明 Edit2:我做了一个简单的代码来告诉你这个问题。当我按下向上键时,显示的两个JPanels必须更改其字符串;在这段代码中,只有一个会做出反应 import java.awt.Color; import java.awt.Font; im
JFrame
,在这个JFrame
里面有两个JPanel
s。当我按下一个键时,他们两个都必须听这个键事件并采取行动。我想获取所有键盘事件,并将它们传递给JPanel
s。你知道怎么做吗
编辑:因为他们必须做不同的事情,我需要两个不同的听众,抱歉没有具体说明
Edit2:我做了一个简单的代码来告诉你这个问题。当我按下向上键时,显示的两个JPanel
s必须更改其字符串;在这段代码中,只有一个会做出反应
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();
}
}
您应该创建一个
XXListener
实现,并通过.addXXListener
将该侦听器添加到您需要的所有组件中。您可以使用观察者模式来实现此功能。
其中一种方法是使用来自的方法(注意有一些更改,但在本例中并不重要),可以重定向、分发来自的多个事件,简单地从一个容器到另一个容器,而不是
KeyListener
,为每个面板使用不同的实现。通过使用“聚焦”组件的“当祖先”输入映射,两个面板都可以响应
附录:由于搜索在找到密钥的有效绑定后结束,下面的示例将事件转发到列表的元素,每个元素都可以通过可用的操作做出不同的响应
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();
}
});
}
}
导入java.awt.EventQueue;
导入java.awt.GridLayout;
导入java.awt.event.ActionEvent;
导入java.awt.event.KeyEvent;
导入java.util.array;
导入java.util.List;
导入javax.swing.AbstractAction;
导入javax.swing.Action;
导入javax.swing.BorderFactory;
导入javax.swing.JComponent;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.KeyStroke;
/**@见http://stackoverflow.com/q/10011564/230513 */
公共类TwoPanelsTest扩展了JFrame{
私人MyPanel one=新MyPanel(“一”);
私人MyPanel 2=新MyPanel(“两”);
私有列表=Arrays.asList(一,二);
公共事务{
超级(“TwoPanelsTest”);
此.setDefaultCloseOperation(关闭时退出);
JPanel面板=新的JPanel(新的网格布局(0,1,10,10));
panel.setBorder(BorderFactory.createEmptyByOrder(10,10,10,10));
小组.增加(一);
增加(两个);
panel.getInputMap(JComponent.WHEN\u焦点组件的祖先\u)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP,0),“UP”);
panel.getActionMap(){
@凌驾
已执行的公共无效操作(操作事件e){
用于(MyPanel:list){
panel.getAction().actionPerformed(e);
}
}
});
本条添加(面板);
这个包();
此.setLocationRelativeTo(空);
此.setVisible(true);
}
私有静态类MyPanel扩展了JPanel{
private String=“将通过其操作进行更新。”;
私人行动行动=新的更新行动(本);
私有字符串名称;
私人标签;
公共MyPanel(字符串名称){
this.name=名称;
this.label=newjlabel(名称+字符串,JLabel.CENTER);
this.setLayout(新的GridLayout());
此参数为.setFocusable(true);
添加(标签);
}
公共行动{
返回动作;
}
私有void更新(){
label.setText(name+”:“+System.nanoTime());
}
私有静态类UpdateAction扩展了AbstractAction{
私人小组;
公共更新操作(MyPanel面板){
this.panel=面板;
}
@凌驾
已执行的公共无效行动(行动事件ae){
panel.update();
}
}
}
公共静态void main(字符串[]args){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
TwoPanelsTest t=新TwoPanelsTest();
}
});
}
}
我知道使用键绑定更好,我在上面发布了一个简单的代码来描述我的问题。当你按下“向上”键时,他们两个都应该改变显示的字符串,但实际上只有一个这样做!我在聚焦窗口中使用了JComponent.WHEN,因为您的输入映射不适合这种情况(如果更改它,您将看到它不起作用)@AR89:我明白您的意思。我在上面添加了一个例子。非常感谢,你的例子效果很好,我将使用它作为模板!另请参见。中概述了此方法。
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();
}
});
}
}