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

  1. 有哪些方法可以检测关键笔划而无需关注事件实施的组件? 这是我的想法:
    即使没有关注myComponent ,在按下某个键时,该动作也应该参与其中。
    ** mousePressed事件的相同问题。 即使未单击组件,也会检测到鼠标单击。**

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

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


我在这里使用了JNativeHooks 示例 ,它的工作原理非常好。 只有Java的任何其他方法?

关于第一个问题,关于KeyStroke的问题,我想你可以使用KeyBinding而不是使用KeyListener,它可以为你提供所需的结果,而不涉及相关组件的焦点相关问题,尽管在Java Dimensions中。

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

虽然如果你将JButton的setMnemonic()方法使用,那么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的解决方法 ,我想也可能适用于此。

  • 所有JComponent都有方法dispatchEvent ,

  • 您可以将mousekey事件从一个JComponent重定向到另一个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); } } }