7
  1. 有哪些方法可以检测击键而不需要关注实现事件的组件?这是我对此的想法:
    即使不关注myComponent,在按键时,动作也应该参与。
    ** 活动的相同问题mousePressed。即使没有点击组件,也会检测到鼠标点击。**

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

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


我在这里使用了 JNativeHooks 示例,它工作得非常好。仅通过Java的任何其他方法?

4

2 回答 2

6

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

在下面的示例中,焦点位于第JTextField一个,因此如果您将 Press CTRL + D,则附加到 the 的 paintActionCustomPanel将起作用,即使焦点位于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);
    }
}

与thingy相关的mousePressed()@mKorbel 像往常一样以令人愉快的方式呈现了整个thingy。

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

于 2013-01-02T12:51:23.047 回答
4
  • 都有JComponent方法dispatchEvent

  • 您可以将mouse&key事件从一个重定向JComponent到另一个

  • 改为JButton使用_doClick()

例如

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class LostMouseEvent {

    private JPanel panel1;

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

            @Override
            public void run() {
                new LostMouseEvent();
            }
        });
    }

    public LostMouseEvent() {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                panel1 = new JPanel() {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(600, 400);
                    }
                };
                JPanel panel2 = new JPanel() {
                    private static final long serialVersionUID = 1L;

                    @Override
                    public Dimension getPreferredSize() {
                        return new Dimension(500, 300);
                    }
                };
                JScrollPane pane = new JScrollPane(panel2);
                panel1.setBorder(BorderFactory.createLineBorder(Color.blue));
                panel2.setBorder(BorderFactory.createLineBorder(Color.green));
                panel1.setLayout(new CircleLayout());
                panel1.add(pane);
                frame.add(panel1);
                MouseListener rml = new RealMouseListener();
                panel1.addMouseListener(rml);
                MouseListener fml = new FakeMouseListener();
                panel2.addMouseListener(fml);
                frame.pack();
                frame.setVisible(true);

            }
        });
    }

    private class RealMouseListener extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent me) {
            System.out.println(me);
            Point point = me.getPoint();
            System.out.println(me.getX());
            System.out.println(me.getXOnScreen());
            System.out.println(me.getY());
            System.out.println(me.getYOnScreen());
        }
    }

    private class FakeMouseListener extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent me) {
            JPanel panel2 = (JPanel) me.getSource();
            MouseEvent newMe = SwingUtilities.convertMouseEvent(panel2, me, panel1);
            System.out.println(newMe.getX());
            System.out.println(newMe.getXOnScreen());
            System.out.println(newMe.getY());
            System.out.println(newMe.getYOnScreen());
            panel1.dispatchEvent(me);
        }
    }
}
于 2013-01-02T08:27:34.320 回答