如何在Java窗口外获取鼠标点击坐标

我需要使用Swing实现一个类,当用户点击屏幕上的任何位置时,可以获取鼠标坐标。 如果我想在我自己的窗口中获取鼠标坐标,我会使用MouseListener ,但我希望它能够工作,即使用户点击我的程序外。

我希望我的课程表现得像KColorChooser :用户点击下拉按钮,他可以点击屏幕上的任意位置以获得该点的颜色。 但我不知道是否可以使用纯Java。

虽然有限,但可能:

为焦点事件添加AWTEventListener。 只要您的应用在单击按钮之前具有焦点,您就会收到焦点丢失事件。 然后查询指针位置。

当然,您的应用程序会失去焦点。 因此,根据您最终要实现的目标,这可能没有用。

如果您不想失去焦点,那么您将不得不暂时截取整个屏幕的屏幕截图并在屏幕填充窗口中显示该屏幕,该窗口像往常一样聆听鼠标点击。

第一种方法的certificate:

 import java.awt.AWTEvent; import java.awt.MouseInfo; import java.awt.Toolkit; import java.awt.event.AWTEventListener; import javax.swing.JFrame; public class Application1 { public static void main(String[] args) { Toolkit.getDefaultToolkit().addAWTEventListener( new Listener(), AWTEvent.MOUSE_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private static class Listener implements AWTEventListener { public void eventDispatched(AWTEvent event) { System.out.print(MouseInfo.getPointerInfo().getLocation() + " | "); System.out.println(event); } } } 

单击应用程序外部生成:

 java.awt.Point[x=198,y=59] | java.awt.event.MouseEvent[MOUSE_EXITED, ... java.awt.Point[x=976,y=503] | java.awt.FocusEvent[FOCUS_LOST, ... 

第二点是在应用程序之外。

忘掉GlassPane ,还有另外100%的原生Java方法可以在OS X和Windows上运行。

Java 一直支持OS X上的窗口的半透明性,Java现在也支持Windows上的窗口的半透明性(因为需要检查Java 1.6.0_10左右)。

所以诀窍是:点击“选择颜色”工具后,您将创建一个覆盖整个屏幕的几乎透明的无边界Java窗口。 您将其alpha设置为10(alpha从0到255)。 这个alpha太低了,用户不会注意到整个屏幕上有一个非常薄的“近乎透明但非常非常非常半透明”的无边框窗口。

现在,当用户点击覆盖整个屏幕的“alpha set to 10 translucent borderless window”时,你得到你的(x,y)。

丢弃无边界Java窗口。

使用RobotgetRgb(x,y)就完成了。

为什么将alpha设置为10而不是0? 因为否则Java不会截获点击,而是直接转到操作系统(至少它是如何用于OS X上的事实)。 有一个门槛,我知道它没有设置为’1’,也没有设置为’2’,它大约是10左右。

编辑我刚刚意识到你需要选择几种颜色,这很棘手,但仍然可以使用100%Java完成。 您可以使用“略微偏离”颜色(受“近乎透明”的“不可见”图层影响) 点击后您必须删除图层,获得正确的像素颜色,然后再次放置“几乎透明”的图层。 现在当然这是一个黑客攻击,但它可以在100%Java中完成。

使用

 import java.awt.MouseInfo; import java.awt.Point; import java.awt.PointerInfo; PointerInfo inf = MouseInfo.getPointerInfo(); Point p = inf.getLocation(); 

px和py将为您提供窗外的坐标。

我不知道是否可以使用纯Java。

它不可能使用纯Java,因为Java只知道属于Java的Windows上的MouseEvents。

这些事件被定向到具有焦点的窗口,从桌面上的所有事件中您只能获得鼠标位置。

正如Keilly所示,它只能获得鼠标位置。

您需要包含本机库

我自己没试过,但也许你可以创建一个全屏,透明的面板/框架等,并添加一个MouseListener。

每次单击之间的位置(x,y)和时间间隔(d)通过命令行参数提供。 这是该计划

 import java.awt.* ; import java.util.* ; public final class ClickMouse extends TimerTask { public static int x, y, d ; public static void main(String[] args) { TimerTask clikMouse = new ClickMouse(); Timer t = new Timer(); /* x = Integer.parseInt(args[0]) ; y = Integer.parseInt(args[1]) ; d = Integer.parseInt(ares[2]) ; */ x = 500; y = 200; d = 5; t.schedule(clikMouse,1000,d*1000); } public void run() { try { Robot bot = new Robot(); bot.mouseMove(x,y); bot.mousePress(java.awt.event.InputEvent.BUTTON1_MASK ); bot.mouseRelease(java.awt.event.InputEvent.BUTTON1_MASK); } catch (Exception e) { System.out.println("Exception occured :" + e.getMessage()); } } } 

我还没有足够的代表留下评论,但这是我对其他技术的评论:

  • 使用本机库:将起作用,但具有明显的分发限制

  • 使用GlassPane填充整个屏幕:GlassPanes必须包含在Window中。

  • 创建一个包含桌面图片的窗口并填满整个屏幕:会工作,但会突然使桌面静止。 光标将不再更改,其他窗口或桌面中的任何动画或video将变得非常静态。

替代解决方案:如果您使用Java 6u10或更高版本,屏幕填充窗口的细化是使窗口完全透明 。 将此窗口放在所有其他窗口的前面,然后听取鼠标点击。 它仍有缺点,例如没有光标变化,但这取决于你想要做什么。

根据SyntaxT3rr0r的回答,我在groovy中创建了一个示例颜色选择器,展示了它如何工作。

 import java.awt.* import java.awt.datatransfer.* //import com.sun.awt.AWTUtilities; import javax.swing.WindowConstants as WC; import javax.swing.SwingConstants as SWC import groovy.swing.SwingBuilder class ColorPicker { SwingBuilder swb = new SwingBuilder() def window; def overlayWindow def mainPanel; def mainLabel; def menu; def transparent = new Color(0, 0, 0, 0); def nearlyTransparent = new Color(0, 0, 0, 26); Color color = new Color(150, 150, 255); def colorHex = { col -> col = col?: color; "#"+Integer.toHexString(col.getRGB())[2..-1] } def getTextColor = { baseColor -> baseColor = baseColor?: color; (baseColor.red*1.5 + baseColor.green*1.5 + baseColor.blue > 400) ? Color.BLACK : Color.WHITE; } def setDisplayColor = {newColor -> mainPanel.background = newColor mainLabel.foreground = getTextColor(newColor) mainLabel.text = colorHex(newColor) } def show(){ menu = swb.popupMenu { // invoker: mainPanel menuItem(text: "Pick Color", actionPerformed: capturePixelColor) menuItem(text: "Copy to Clipboard", actionPerformed: { Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(new StringSelection(colorHex()), null); }) separator() menuItem(text: "Close", actionPerformed: {dispose()}) } window = swb.frame( title: "Color Picker", location:[50,50], size:[60, 60], resizable: false, undecorated: true, alwaysOnTop: true, defaultCloseOperation:WC.EXIT_ON_CLOSE ){ def textColor = getTextColor() mainPanel = panel( constraints: BorderLayout.CENTER, border: lineBorder(color: Color.BLACK), componentPopupMenu: menu){ borderLayout() mainLabel = label(text: "--", constraints: BorderLayout.CENTER, horizontalAlignment: SWC.CENTER) } } setDisplayColor(color); window.show(); } def capturePixelColor = { def screenSize = Toolkit.getDefaultToolkit().screenSize overlayWindow = swb.frame( location:[0,0], size: screenSize, resizable: false, undecorated: true, alwaysOnTop: true, defaultCloseOperation:WC.DISPOSE_ON_CLOSE, show: true, background: nearlyTransparent, // AWTUtilities.setWindowOpacity(overlayWindow, 0.1f); cursor: Cursor.CROSSHAIR_CURSOR, mouseClicked: {event -> int x = event.getXOnScreen() // or maybe getX() is enough int y = event.getYOnScreen() overlayWindow.dispose() overlayWindow = null color = new Robot().getPixelColor(x, y) setDisplayColor(color) } ) } public static void main(String...args){ println "Welcome to ColorPicker" def picker = new ColorPicker() picker.show() } } 

这可能是一个小技巧。 应该是100%跨平台(在Linux和Windows上测试)。 基本上,你创建一个小的JWindow,使它“alwaysOnTop”并使用鼠标使用计时器移动它。

有关详细信息,请参阅我的答案。

看,我明白我迟到了7年……

这是对Keilly的回答的重新制作,它允许在任何地方点击鼠标按钮时获取。 主要问题是全屏游戏总是没有重点,处理起来很烦人。

这是代码:

 import java.awt.AWTEvent; import java.awt.MouseInfo; import java.awt.Point; import java.awt.Toolkit; import java.awt.event.AWTEventListener; import javax.swing.JFrame; public class Main { public static JFrame frame = new JFrame(); public static void main(String[] args) { Toolkit.getDefaultToolkit().addAWTEventListener( new Listener(), AWTEvent.MOUSE_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); frame.setAlwaysOnTop(true); frame.setLocation(1, 1); } private static class Listener implements AWTEventListener { public void eventDispatched(AWTEvent event) { // We do not want the event to show twice, // as it shows for focusing and unfocusing if(event.getID() == 1004) { Point p = MouseInfo.getPointerInfo().getLocation(); System.out.println("Mouse Clicked at " + px + ", " + py); } // The frame was just unfocused! To make // sure we get the next mouse click, we // need to focus it again! frame.setVisible(true); } } }