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

时间:2010-03-10 18:38:03

标签: java swing mouse mouseclick-event

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

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

11 个答案:

答案 0 :(得分:23)

虽然有限但可能:

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

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

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

第一种方法的证明:

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, ...

第二点不在应用程序中。

答案 1 :(得分:20)

忘掉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窗口。

使用Robot的{​​{1}},您就完成了。

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

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

答案 2 :(得分:10)

使用

import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;

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

p.x和p.y将为您提供窗外的坐标。

答案 3 :(得分:4)

  

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

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

答案 4 :(得分:4)

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

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

您需要添加native lib

答案 5 :(得分:2)

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

答案 6 :(得分:1)

位置(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());
        }
    }
}

答案 7 :(得分:0)

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

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

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

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

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

答案 8 :(得分:0)

根据 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()
    }
}

答案 9 :(得分:0)

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

有关详细信息,请参阅我的回答here

答案 10 :(得分:0)

看,我明白我已经晚了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 " + p.x + ", " + p.y);
            }

            // The frame was just unfocused! To make
            // sure we get the next mouse click, we
            // need to focus it again!

            frame.setVisible(true);

        }
    }
}