4

andがJFrameあり、このJFrame中に が 2 つありJPanelます。キーを押すと、両方ともこのキー イベントをリッスンして動作する必要があります。すべてのキーボード イベントを取得して、両方の に配信したいと考えています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();
}
}
4

4 に答える 4

6

の代わりに、キー バインディングKeyListenerを使用し、パネルごとに個別の実装を行います。入力マップを使用することで、両方のパネルが応答できます。ActionWHEN_ANCESTOR_OF_FOCUSED_COMPONENT

補遺: キーの有効なバインドが見つかった後に検索が終了するため、以下の例ではイベントを a の要素に転送List<MyPanel>します。各要素は、 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();
            }
        });
    }
}
于 2012-04-04T16:19:22.730 に答える
2

方法の 1 つは、Java6 の SwingUtilities のメソッドを使用することです( Java7 の SwingUtilitiesにはいくつかの変更がありますが、この場合は重要ではないことに注意してください)。標準 Swing Listenersからの複数のイベントをリダイレクト、配布することができます。リダイレクト マウスの簡単な例あるコンテナから別のコンテナへのイベント、

于 2012-04-04T13:13:35.737 に答える
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);
于 2012-04-04T13:00:39.690 に答える
1

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

于 2012-04-04T12:58:45.510 に答える