无需关注实现事件的组件即可检测击键的方法有哪些?这是我的想法:
即使不关注myComponent
,在按下一个键时, Action 也应该参与。
**mousePressed
事件的相同问题。即使没有点击组件,也会检测到鼠标点击。**myComponent.addKeyListener( new KeyAdapter() { @Override public void keyPressed( KeyEvent e ){ // My action here } });
在回答
问题 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/