4

問題の説明: JFrame があり、この JFrame 内にボタン付きの JPanel があります。ボタンを押すと、アクション リスナーが現在の JPanel を新しい JPanel に変更します。新しい JPanel には、他の 2 つの JPanel が含まれています。ユーザーがキーを「上」に押すと、両方で何かが作成されます。問題は、JPanel を新しいものに変更すると、「上」キーを押しても何も起こらないことです。

コードは次のとおりです。これは SSCCE であるため、コピーして貼り付けるだけで、その機能を確認できます。

この変更されたコードは、私が時々「解決」した別の質問から来ています。2 つの JPanel に同じイベントをリッスンさせる方法は? (コードは私が選択した回答にあります)。

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

public class TwoPanelsTest extends JFrame {

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

public TwoPanelsTest() {
    super("TwoPanelsTest");
    panelsController= new PanelsController(this);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.setSize(400,400);
    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();
        }
    }
}//MyPanel

private static class ButtonPanel extends JPanel{
    private JButton button ;
    private PanelsController panelsController;

    public ButtonPanel(PanelsController panelsController){
        this.panelsController=panelsController;

        button = new JButton("Button");
        button.setActionCommand("buttonPressed");
        button.addActionListener(this.panelsController);
        this.setFocusable(true);
        add(button);
    }
}//ButtonPanel

private static class PanelsController implements ActionListener {

    private TwoPanelsTest twoPanelsTest;

    public PanelsController(TwoPanelsTest twoPanelsTest){
        this.twoPanelsTest=twoPanelsTest;
        this.twoPanelsTest.getContentPane().add(new ButtonPanel(this));
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        if (ae.getActionCommand().equals("buttonPressed")){
            twoPanelsTest.getContentPane().removeAll();
            twoPanelsTest.getContentPane().invalidate();

            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);
                    }
                }
            });
            twoPanelsTest.getContentPane().add(panel);
            twoPanelsTest.validate();
            twoPanelsTest.repaint();
        }
    }//ActionPerformed

}//PanelsController

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

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

1 に答える 1

4

非常に簡単です。内部にコンポーネントがない 2 つのパネルがあり、ホットキーの使用をリッスンする場合:

panel.getInputMap ( JComponent.WHEN_IN_FOCUSED_WINDOW )
     .put ( KeyStroke.getKeyStroke ( KeyEvent.VK_UP, 0 ), "up" );

JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT の代わりに JComponent.WHEN_IN_FOCUSED_WINDOW。

それ以外の場合は、重要なイベントをキャッチできるように、パネル内に何かをフォーカスする必要があります。

ちなみに、Java アプリケーション ウィンドウ内でグローバル ホットキーをリッスンする別の方法もあります。

Toolkit.getDefaultToolkit ().addAWTEventListener ( new AWTEventListener ()
{
    public void eventDispatched ( AWTEvent event )
    {
        // All application key events will be passed here
    }
}, AWTEvent.KEY_EVENT_MASK );
于 2012-04-17T07:05:27.727 に答える