java - 未聚焦组件中的 KeyPressed 和 mousePressed 事件

标签 java swing focus mouseevent key-events

  1. 无需关注实现事件的组件即可检测击键的方法有哪些?这是我的想法:
    即使不关注 myComponent,在按下一个键时, Action 也应该参与。
    ** mousePressed 事件的相同问题。即使没有点击组件,也会检测到鼠标点击。**

    myComponent.addKeyListener( new KeyAdapter() {
     @Override
     public void keyPressed( KeyEvent e ){
      // My action here         
     }
    
    });
    
  2. 在回答问题 1 后,即使应用程序在后台运行,也可以完成吗?假设我有一个浏览器,每次我点击或按下某个键时,都会执行给定的操作。

我也接受阅读建议作为答案。如果您的答案与 KeyBinding 相关,请详细说明。非常感谢所有的回答和评论。


我用了JNativeHooks examples here它工作得很好。仅通过 Java 的任何其他方法?

最佳答案

对于第一个问题,关于 KeyStroke 的东西,我想你可以使用 KeyBinding而不是使用 KeyListener,它可以为您提供所需的结果,而无需关注相关组件的焦点相关问题,尽管在 Java 维度中。

在下面的示例中,焦点首先位于 JTextField 上,因此如果您按 CTRL + D,那么 paintAction thingy 附加到 CustomPanel 将起作用,即使焦点在于 JTextField

尽管如果您将使用 setMnemonic() JButton 的方法,然后 JButton 将获得焦点并执行与其关联的自己的操作,即绘制椭圆。您可以通过按 ALT + C 查看所需的效果。再次执行绘图相关的事情,有问题的两个组件都不需要焦点,但它们仍然响应 KeyStrokes。

示例代码如下:

import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;

public class SSCCE
{
    private final int WIDTH = 500;
    private final int HEIGHT = 500;
    private CustomPanel customPanel;
    private JButton circleButton;
    private JTextField tfield;
    private Random random;
    private int mode;

    private Action paintAction = new AbstractAction()
    {
        @Override
        public void actionPerformed(ActionEvent ae)
        {
            mode = random.nextInt(3);
            Color color = new Color(random.nextFloat(), random.nextFloat()
                                                        , random.nextFloat(), random.nextFloat());
            customPanel.setValues(random.nextInt(WIDTH), 
                            random.nextInt(HEIGHT), random.nextInt(WIDTH), 
                                                                    random.nextInt(HEIGHT), color, mode);
        }
    };

    private ActionListener buttonAction = new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent ae)
        {
            Color color = new Color(random.nextFloat(), random.nextFloat()
                                                        , random.nextFloat(), random.nextFloat());
            customPanel.setValues(random.nextInt(WIDTH), 
                            random.nextInt(HEIGHT), random.nextInt(WIDTH), 
                                                                    random.nextInt(HEIGHT), color, 2);
        }
    };

    public SSCCE()
    {
        random = new Random();
    }

    private void displayGUI()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane = new JPanel();
        contentPane.setLayout(new BorderLayout(5, 5));

        customPanel = new CustomPanel();
        customPanel.getInputMap(
            JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_D
                    , InputEvent.CTRL_DOWN_MASK), "paintAction");
        customPanel.getActionMap().put("paintAction", paintAction);

        JPanel footerPanel = new JPanel();
        circleButton = new JButton("Draw Circle");
        circleButton.setMnemonic(KeyEvent.VK_C);
        circleButton.addActionListener(buttonAction);

        tfield = new JTextField(20);
        tfield.setText("USELESS, just to get the focus for itself.");
        tfield.requestFocusInWindow();
        footerPanel.add(tfield);
        footerPanel.add(circleButton);

        contentPane.add(customPanel, BorderLayout.CENTER);
        contentPane.add(footerPanel, BorderLayout.PAGE_END);

        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                new SSCCE().displayGUI();
            }
        });
    }
}

class CustomPanel extends JPanel
{
    private final int WIDTH = 500;
    private final int HEIGHT = 500;
    private int mode = 0;
    private Color colorShape;
    private int x = 0;
    private int y = 0;
    private int width = 0;
    private int height = 0;

    public void setValues(int x, int y, int w, int h, Color color, int mode)
    {
        this.x = x;
        this.y = y;
        this.width = w;
        this.height = h;
        this.colorShape = color;
        this.mode = mode;

        repaint();
    }

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(WIDTH, HEIGHT));
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(colorShape);
        if (mode == 1)
            g.fillRect(x, y, width, height);
        else if (mode == 2)
            g.fillOval(x, y, width, height);
    }
}

mousePressed() 有关的东西,@mKorbel,以令人愉快的方式像往常一样展示了整个东西。

关于你的第二个问题,你自己似乎已经做了一些功课。似乎使用您在问题中显示的内容是捕获操作系统相关事件并将其传输到您的 Java 应用程序或 Java Native Interface 的解决方法。 ,我想也许也可以解决这个问题。

关于java - 未聚焦组件中的 KeyPressed 和 mousePressed 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14118734/

相关文章:

javascript - 更改焦点 ExtJs 上的文本字段颜色

.net - 获取 WPF 窗口中当前聚焦的元素/控件

java - 是否有可能在编译时获取方法的 "potential"堆栈跟踪?

java - 使用 google-cloud-speech 时在 APK project.properties 中复制的重复文件

java - MVP GWT 项目中的 Singleton

java - 了解 Java Swing 屏幕缓冲区内存使用(欢迎阅读 Material )

java - 是循环内枚举的开关好风格

java - 摆弄 Java Graphics,这工作_一次_

java - 如何在 Java Swing 中创建可折叠和可展开的面板?

angular - *ngIf 带有焦点指令