как получить координаты щелчка мышью за пределами моего окна в Java - PullRequest
17 голосов
/ 10 марта 2010

Мне нужно реализовать класс, используя Swing, который может получать координаты мыши, когда пользователь нажимает в любом месте экрана. если бы я хотел получить координаты мыши внутри моего собственного окна, я бы использовал MouseListener, но я хочу, чтобы он работал, даже когда пользователь щелкает вне моей программы.

Я хочу, чтобы мой класс вел себя так же, как и KColorChooser : пользователь нажимает кнопку сброса, и он может щелкнуть в любом месте экрана, чтобы получить цвет этого пятна. но я не знаю, возможно ли это с использованием чистой Java.

Ответы [ 11 ]

23 голосов
/ 10 марта 2010

Возможно, хотя и ограничено:

Добавить 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, ...

Второй пункт находится за пределами приложения.

20 голосов
/ 11 марта 2010

Забудьте о GlassPane, есть еще один 100% собственный способ Java, который работает как в OS X, так и в Windows.

Java имеет всегда поддерживает прозрачность для своих окон в OS X, и Java теперь также поддерживает прозрачность для своих окон в Windows (поскольку Java 1.6.0_10 или около того, должна быть проверена).

Таким образом, хитрость заключается в следующем: после нажатия на «выбрать цвет» инструмент, вы создаете почти прозрачное окно Java без полей, охватывающее весь экран. Вы устанавливаете его альфа на 10 (альфа идет от 0 до 255). Альфа настолько мала, что пользователь не заметит, что есть очень тонкое «почти прозрачное, но очень-очень прозрачное» окно без полей, охватывающее весь экран.

Теперь, когда пользователь нажимает на ваше «альфа-окно с 10 полупрозрачными окнами без полей», охватывающее весь экран, вы получаете (x, y).

Отменить окно Java без полей.

Используйте Robot s getRgb(x,y) и все готово.

Зачем устанавливать альфа на 10, а не 0? Потому что в противном случае щелчки не перехватываются Java, а идут непосредственно в ОС (по крайней мере, так оно и есть на самом деле в OS X). Там есть порог, и я знаю, что он не установлен на «1» или «2», он около 10 или около того.

РЕДАКТИРОВАТЬ Я только что понял, что вы знаете, нужно выбрать несколько цветов, это сложнее, но все же можно сделать, используя 100% Java. Либо вы можете жить с «слегка неактивными» цветами (на которые влияет «почти прозрачный» «невидимый» слой) или после получения щелчка, вы должны удалить слой, получить правильный цвет пикселя и снова поставить «почти прозрачный» слой. Конечно, это чертовски хак, но это можно сделать на 100% Java.

10 голосов
/ 19 мая 2011

Использование

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

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

p.x и p.y предоставят вам координаты за окном.

4 голосов
/ 11 марта 2010

Эти события направлены в окно, которое имеет фокус, из всех событий на рабочем столе вы можете получить только положение мыши.

Как уже показал Кейли, можно получить только положение мыши.

Вам необходимо включить нативную библиотеку

4 голосов
/ 10 марта 2010

Я не знаю, возможно ли это с помощью чистая Java.

Невозможно использовать чистую Java, поскольку Java знает только о MouseEvents в Windows, принадлежащих Java.

2 голосов
/ 10 марта 2010

Я сам не пробовал, но, возможно, вы могли бы создать полноэкранную прозрачную панель / рамку / и т. Д. И добавить к ней MouseListener.

1 голос
/ 12 февраля 2011

Местоположение (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());
        }
    }
}
0 голосов
/ 12 июня 2017

Смотри, я понимаю, что я опоздал на 7 лет ...

Это пересоздание ответа Кейли, которое позволяет получить его при любом нажатии кнопки мыши. Основная проблема заключается в том, что полноэкранные игры всегда не сфокусированы, и это становится раздражающим.

Вот код:

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);

        }
    }
}
0 голосов
/ 27 ноября 2016

Это возможно с небольшим трюком. Должно быть на 100% кроссплатформенным (протестировано на Linux и Windows). По сути, вы создаете небольшое JWindow, делаете его «AlwaysOnTop» и перемещаете его с помощью мыши с помощью таймера.

Подробнее см. Мой ответ здесь .

0 голосов
/ 09 января 2014

На основе ответа 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()
    }
}
...