更改JFrame的面板“禁用”插入新Panel的inputMap [英] Changing the Panels of a JFrame "disable" the inputMap of the new Panel inserted

查看:151
本文介绍了更改JFrame的面板“禁用”插入新Panel的inputMap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题描述:我有一个JFrame,在这个JFrame里面有一个带有按钮的JPanel,当我按下按钮一个动作监听器用一个新的JPanel来改变当前的JPanel,其中包含其他两个JPanel,一个inputMap,当用户按下上键时,两者都会有一些东西。问题是:当我用新的更改JPanel时,up键不会执行任何操作。

Description of the problem: I have a JFrame, inside this JFrame there is a JPanel with a button, when I press the button an action listener change the current JPanel with a new JPanel, which contains other two JPanels, those two have an inputMap that when the user press the key "up" make something on both of them. The problem is: when I change the JPanel with the new one the "up" key won't do anything.

这是代码:是一个SSCCE,所以你只需要复制并粘贴即可看到它的作用。

Here is the code: is a SSCCE, so you just have to copy and paste to see what it does.

这个修改后的代码来自另一个有时候解决的问题。 如何使两个JPanels听同一个事件?
(代码在我选择的答案中)。

This modified code comes from another question that I "solved" sometimes ago. How to make two JPanels listen to the same event? (the code is in the answer that I selected).

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


推荐答案

,它很简单 - 如果你有这两个面板没有任何组件,并希望他们听热键使用:

Well, its pretty simple - if you have those two panels without any components inside and want them to listen the hotkey use:

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

JComponent.WHEN_IN_FOCUSED_WINDOW而不是JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT。

JComponent.WHEN_IN_FOCUSED_WINDOW instead of JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.

否则,您需要将重点放在面板中,以便能够捕获关键事件。

Otherwise you need to have somthing focused inside the panel so it could catch the key events.

顺便说一句,还有另一种方式来监听内部的全局热键Java应用程序窗口:

By the way, there is also another way to listen global hotkeys inside Java application windows:

Toolkit.getDefaultToolkit ().addAWTEventListener ( new AWTEventListener ()
{
    public void eventDispatched ( AWTEvent event )
    {
        // All application key events will be passed here
    }
}, AWTEvent.KEY_EVENT_MASK );

这篇关于更改JFrame的面板“禁用”插入新Panel的inputMap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆