如何解决java鼠标和键盘事件之间的冲突?

时间:2015-04-15 04:54:09

标签: java events

在运行Java 1.7的Windows 8系统上,我发现关键事件正在干扰鼠标事件。这是一个例子。这是一个愚蠢的事情,但它说明了在更复杂的设置中出现的问题。我发现,一旦我按下了钥匙,我就无法做到 移动鼠标直到我松开钥匙。我不知道为什么这不起作用。

事实上,更多的实验表明,这似乎根本不是一个Java问题 - 所以我不确定在论坛中我应该怎么做这个问题。

正如MadProgrammer所述,这是一个键盘自动重复问题。事实上, 如果您按一个键然后快速移动鼠标(在自动重复开始之前),您可以画一条短线。因此,来自自动重复的关键事件似乎阻止了屏幕上的鼠标移动。出现了 在整个Windows界面中发生。例如,我使用辅助功能设置来关闭自动重复 - 所以在NotePad中,比如说,按键不再重复。但是,如果按住某个键,鼠标仍然会锁定。即使它不在NotePad窗口中,它也会锁定。

显然这不是Java问题 - 我刚刚在这里注意到它。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

// Demo key/mouse event interference
// Pressing and holding any key, moving the mouse
// and releasing the key should draw a line.
// written by mcslattery - april 2015
public class KeyMouse extends JPanel {
    public static final int WID = 500;
    public static final int HT = 400;

    int x1,y1,x2,y2;
    boolean drawn = false;
    int mx,my;

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new KeyMouse()); f.pack();
        f.setVisible(true);
    }

    public KeyMouse() {
        super();
        setPreferredSize(new Dimension(WID, HT));
        addMouseMotionListener(new MseL());
        addKeyListener(new KeyL());
        setFocusable(true); requestFocus();
    }

    public void paintComponent(Graphics g) {
        g.setColor(Color.white);
        g.fillRect(0,0,WID,HT);
        if (drawn) {
            g.setColor(Color.black);
            g.drawLine(x1, y1, x2, y2);
        }   
    }

    class MseL extends MouseMotionAdapter {
        public void mouseMoved(MouseEvent e) {
            mx = e.getX(); my = e.getY();   
        }
    }

    class KeyL extends KeyAdapter {
        public void keyPressed(KeyEvent e) {
            x1 = mx; y1 = my;
            drawn = false;
            repaint();
        }

        public void keyReleased(KeyEvent e) {
            x2 = mx; y2 = my;
            drawn = true;
            repaint();
        }
    }
}

1 个答案:

答案 0 :(得分:1)

问题不在于操作系统或Java,而是在假设keyPressed如何工作。

按下时,一个键将触发keyPressed事件,在特定于操作系统的延迟之后,它将触发重复事件,直到释放该键,同时调用keyReleased

这意味着......

public void keyPressed(KeyEvent e) {
    x1 = mx;
    y1 = my;
    drawn = false;
    repaint();
}

正在不断更新x1y1值,使其与当前鼠标位置相同...

相反,如果尚未设置起始值,则添加一个标志,该标志可用于确定是否已按下该键。释放后,重置标志,例如......

private boolean pressed = false;

public void keyPressed(KeyEvent e) {
    if (!pressed) {
        pressed = true;
        x1 = mx;
        y1 = my;
        drawn = false;
        repaint();
    }
}

public void keyReleased(KeyEvent e) {
    pressed = false;

旁注:

我并不特别符合您的paintComponent方法......

public void paintComponent(Graphics g) {
    g.setColor(Color.white);
    g.fillRect(0,0,WID,HT);

三个主要原因......

  1. 该组件可能不是WID宽或HT高度
  2. 您可以在构造函数和setBackground(Color.WHITE)中使用super.paintComponent(g)来获得相同的结果,如果paintComponent由于某种原因发生更改通常会更安全
  3. 这个方法不需要public,你永远不需要任何人称之为