使用ctrl + w

时间:2018-03-27 08:50:45

标签: java swing key-bindings

我有一个使用大量JFrame个对象的Java程序。为了更容易清理桌面,我想实现当前的焦点窗口可以用 Ctrl + w 关闭。

我尝试使用Action actionPerformed方法包含此内容的键绑定(在任何视图的超类中):

frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));

这很有效 - 只要我只使用一个窗口。它只有在最后打开的帧被聚焦时才有效,并且只关闭那个帧。

我的问题是:

  1. 为什么键绑定的行为是这样的? (我想这是设计的。)
  2. 如何在不向KeyListener添加任何单个组件的情况下每帧创建一个键绑定。

1 个答案:

答案 0 :(得分:0)

  

为什么键绑定的行为如下? (我想这是设计的。)

我猜你做错了什么,但没有任何示例代码,就不可能知道什么

  

如何在不向KeyListener添加任何单个组件的情况下每帧创建一个键绑定

您可以通过多种方式实现这一目标......

基于全球的解决方案......

一种方法是采用“全局”方法,使用不依赖于您从根解决方案扩展的系统,但可以应用于任何现有或未来项目。

AWTEventListener

一种解决方案可能是将AWTEventListener附加到Toolkit。这是一个非常低级别,您可以访问系统正在处理的所有关键事件

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import javax.swing.FocusManager;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    private int count = 0;
    private int xPos = 10;
    private int yPos = 10;

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                installKeyboardMonitor();
                for (int index = 0; index < 10; index++) {
                    makeWindow();
                }
            }
        });
    }

    public static void installKeyboardMonitor() {
        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
            @Override
            public void eventDispatched(AWTEvent event) {
                KeyEvent ke = (KeyEvent) event;
                if (ke.getID() == KeyEvent.KEY_PRESSED) {
                    System.out.println("Pressed");
                    if (ke.getKeyCode() == KeyEvent.VK_W) {
                        System.out.println("W Key");
                        if (ke.isControlDown()) {
                            System.out.println("Control down");
                            Window window = FocusManager.getCurrentManager().getActiveWindow();
                            if (window != null) {
                                window.dispose();
                            }
                        }
                    }
                }
            }
        }, AWTEvent.KEY_EVENT_MASK);
    }

    public void makeWindow() {
        count++;
        JFrame frame = new JFrame("Test " + count);
        frame.setContentPane(new JPanel(new BorderLayout()) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        });
        frame.add(new JLabel("Window " + count));
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setLocation(xPos, yPos);
        frame.setVisible(true);
        xPos += 100;
        yPos += 100;
    }

}

KeyEventDispatcher

这比AWTEventListener稍微低一些,但它只关注KeyEvent s,这使得它更容易管理,但基本上是相同的想法

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.event.KeyEvent;
import javax.swing.FocusManager;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    private int count = 0;
    private int xPos = 10;
    private int yPos = 10;

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                installKeyboardMonitor();
                for (int index = 0; index < 10; index++) {
                    makeWindow();
                }
            }
        });
    }

    public static void installKeyboardMonitor() {
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new KeyEventDispatcher() {
            @Override
            public boolean dispatchKeyEvent(KeyEvent ke) {
                if (ke.getID() == KeyEvent.KEY_PRESSED) {
                    System.out.println("Pressed");
                    if (ke.getKeyCode() == KeyEvent.VK_W) {
                        System.out.println("W Key");
                        if (ke.isControlDown()) {
                            System.out.println("Control down");
                            Window window = FocusManager.getCurrentManager().getActiveWindow();
                            if (window != null) {
                                window.dispose();
                                return true;
                            }
                        }
                    }
                }
                return false;
            }
        });
    }

    public void makeWindow() {
        count++;
        JFrame frame = new JFrame("Test " + count);
        frame.setContentPane(new JPanel(new BorderLayout()) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        });
        frame.add(new JLabel("Window " + count));
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setLocation(xPos, yPos);
        frame.setVisible(true);
        xPos += 100;
        yPos += 100;
    }

}

可配置解决方案

另一种解决方案是提供基于“配置”的解决方案。这与具有基本组件的概念类似,但可以使您免于被锁定到单个扩展点。

这种方法有点麻烦,因为您实际上需要记住应用于应用程序可能创建的每个窗口和对话框。

它只是使用Key Bindings API为Windows JRootPane注册绑定,但您可以使用任何您知道不会从窗口中删除的组件。

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Window;
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.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    private int count = 0;
    private int xPos = 10;
    private int yPos = 10;

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                for (int index = 0; index < 10; index++) {
                    makeWindow();
                }
            }
        });
    }

    public static void installKeyBindings(JComponent component) {
        InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = component.getActionMap();

        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_DOWN_MASK), "Window.close");
        actionMap.put("Window.close", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Window window = SwingUtilities.windowForComponent(component);
                if (window != null) {
                    window.dispose();
                }
            }
        });
    }

    public void makeWindow() {
        count++;
        JFrame frame = new JFrame("Test " + count);
        installKeyBindings(frame.getRootPane());
        frame.setContentPane(new JPanel(new BorderLayout()) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        });
        frame.add(new JLabel("Window " + count));
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setLocation(xPos, yPos);
        frame.setVisible(true);
        xPos += 100;
        yPos += 100;
    }

}

思考后

这只是三种可能的解决方案。围绕每个解决方案提供更可配置的解决方案并不需要花费太多精力(因此您可以提供关键笔划),但我会将其留给您