我正在开发Java FX应用程序,其中涉及使用moushook捕获用鼠标选择的文本。在使用Java 8编译和运行时,此方法可以正常工作,但是当前需要使用Java 10,这在Mac OS X上引起了问题(在Windows 10上运行时没有问题)。
问题在于,当从文档中选择文本时(例如TexEdit中的文本),所选文本将被删除并替换为“ c”,而不是被复制。这种情况并非每次都发生,但会经常发生。
我将mouseHook类简化为一个显示问题的非常基本的测试用例:
MouseHook类--------------------------------------------- ------------
package problem;
import org.jnativehook.GlobalScreen;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.KeyEvent;
import java.util.Timer;
import java.util.TimerTask;
public class MouseHook implements NativeMouseInputListener
{
private static MouseHook mouseHook = null;
private Robot mouseRobot = null;
private boolean mouseLeftButtonDown = false;
private boolean dragged = false;
private MouseHook()
{
//disable console output from JNativeHook's internal logger (mouse-tracking, etc)
java.util.logging.Logger logger = java.util.logging.Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(java.util.logging.Level.OFF);
}
public static synchronized MouseHook getInstance()
{
if(mouseHook == null)
{
mouseHook = new MouseHook();
GlobalScreen.addNativeMouseListener(mouseHook);
GlobalScreen.addNativeMouseMotionListener(mouseHook);
}
return mouseHook;
}
@Override
public void nativeMousePressed(NativeMouseEvent e)
{
//If left button pressed, set mouseLeftButtonDown and look-out for dragging
if(e.getButton() == NativeMouseEvent.BUTTON1)
{
mouseLeftButtonDown = true;
}
}
@Override
public void nativeMouseDragged(NativeMouseEvent e)
{
//only record a drag if left mouse button is held down.
//NativeMouseEvent doesn't say which button was the source, hence test the variable.
if(mouseLeftButtonDown)
{
dragged = true;
}
}
@Override
public void nativeMouseReleased(NativeMouseEvent e)
{
//copy text if the mouse was dragged while the left mouse button was held down.
if(e.getButton() == NativeMouseEvent.BUTTON1)
{
final Timer timer = new Timer("ReleaseDetect");
timer.schedule(new TimerTask()
{
@Override
public void run()
{
if(dragged)
{
copy();
dragged = false;
}
mouseLeftButtonDown = false;
timer.cancel();
}
}, 500);
}
}
@Override
public void nativeMouseClicked(NativeMouseEvent e)
{}
@Override
public void nativeMouseMoved(NativeMouseEvent e)
{}
private synchronized void copy()
{
try
{
if(mouseRobot == null)
{
mouseRobot = new Robot();
mouseRobot.setAutoDelay(100);
mouseRobot.setAutoWaitForIdle(true);
}
if(System.getProperty("os.name").toLowerCase().contains("mac"))
{
mouseRobot.keyPress(KeyEvent.VK_META);
mouseRobot.keyPress(KeyEvent.VK_C);
mouseRobot.keyRelease(KeyEvent.VK_C);
mouseRobot.keyRelease(KeyEvent.VK_META);
}
else
{
mouseRobot.keyPress(KeyEvent.VK_CONTROL);
mouseRobot.keyPress(KeyEvent.VK_C);
mouseRobot.keyRelease(KeyEvent.VK_C);
mouseRobot.keyRelease(KeyEvent.VK_CONTROL);
}
Thread.sleep(250);
Transferable t=Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
if(t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor))
{
String activeContent = (String) t.getTransferData(DataFlavor.stringFlavor);
System.out.println(activeContent);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
运行示例的类------------------------------------------ --------------
package problem;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
public class Runnit
{
private static MouseHook mouseHook;
public static void main(String[] args)
{
try
{
GlobalScreen.registerNativeHook();
}
catch(NativeHookException e)
{
System.out.println("Cannot set up the NativeHook listener on the GlobalScreen");
}
mouseHook = MouseHook.getInstance();
}
}
我正在使用Oracle的Java 10.0.2和jNativeHook 2.1.0,以及在Mac mini上使用Mac OS High Sierra(10.13.6)。
问题似乎出在使用java.awt.Robot,而不是jNativeHook。
例如如果我将VK_C keyPress / Release替换为VK_B,则鼠标钩会删除所选文本并将其替换为“ b”。
我的直觉是VK_META按键被忽略了。我尝试在按键之前延迟一下,但这没什么区别。
我也尝试过使用其他鼠标和其他人的Macintosh,但是问题仍然存在。就像我说的那样,只有在使用Java 10编译并运行代码的情况下,它才会在Mac OS X而不是Windows 10上发生。
如果有人对这是一个失败的原因,或者有解决方法的任何想法,我将不胜感激。可能是因为我通常在Windows上工作并且对Mac OS X不太了解,所以错过了一些明显的事情。