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

时间:2013-01-02 08:09:16

标签: java swing focus mouseevent key-events

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

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

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


    我使用了JNativeHooks examples here,它的效果非常好。仅仅使用Java的任何其他方法?

2 个答案:

答案 0 :(得分:6)

对于第一个问题,关于KeyStroke的问题,我猜你可以使用KeyBinding代替使用KeyListener,它可以为你提供所需的结果,而不会引起相关组件的焦点相关问题,尽管Java维度。

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

虽然如果您将JButton方法用于JButton,那么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); } } 将获得焦点并将执行与其相关的自己的操作,即绘制椭圆。您可以通过按 ALT + C 查看,以查看所需的效果。再次执行绘图相关的东西,有问题的组件都不需要焦点,但它们仍然响应KeyStrokes。

以下是示例代码:

mousePressed()

与{{1}} thingy相关,@ mKorbel以愉快的方式像往常一样呈现了整个事物。

关于你的第二个问题,看起来你自己已经完成了一些功课。似乎使用您在问题中显示的内容是捕获与操作系统相关的事件并将其传输到Java应用程序或setMnemonic()的解决方法,我想也可能适用于此。

答案 1 :(得分: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);
        }
    }
}