Событие KeyPressed и mousePressed в несосредоточенном компоненте
Каковы несколько способов обнаружения нажатия клавиш без необходимости фокусировки на компоненте, в котором было реализовано событие? Вот моя идея по этому поводу:
Даже не сосредотачиваясь наmyComponent
после нажатия клавиши действие должно принять участие.
** Тот же вопрос дляmousePressed
событие. Щелчок мыши будет обнаружен, даже если не нажимать на компонент.**myComponent.addKeyListener( new KeyAdapter() { @Override public void keyPressed( KeyEvent e ){ // My action here } });
После ответа
Question1
Можно ли это сделать, даже если приложение работает в фоновом режиме? Скажем, у меня есть браузер, каждый раз, когда я нажимаю или нажимаю клавишу, данное действие будет выполняться.
Я также принимаю предложения для чтения в качестве ответа. Если ваш ответ будет связан с KeyBinding, пожалуйста, уточните. Все ответы и комментарии будут с благодарностью.
Я использовал примеры JNativeHooks здесь, и он прекрасно работает. Любой другой метод только на Java?
2 ответа
Что касается первого вопроса, касающегося KeyStroke, я думаю, вы можете использовать KeyBinding вместо KeyListener, который может дать вам желаемый результат, без проблем, связанных с фокусом рассматриваемого компонента, хотя и в рамках Java Dimensions.
В приведенном ниже примере основное внимание уделяется JTextField
во-первых, так что если вы нажмете CTRL + D, то штука paintAction, прикрепленная к CustomPanel
будет работать, хотя основное внимание уделяется JTextField
,
Хотя, если вы будете использовать метод setMnemonic() для JButton
тогда JButton
получит фокус и выполнит свое собственное действие, связанное с ним, то есть нарисовать овалы. Это вы можете увидеть, нажав ALT + C, чтобы увидеть желаемый эффект. Опять же, для выполнения связанных с рисованием вещей, оба рассматриваемых компонента не нуждаются в фокусе, но все же они реагируют на нажатия клавиш.
Вот пример кода:
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, я думаю, что это также может сработать.
все
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);
}
}
}