Подтвердить что ты не робот

Как получить координаты щелчка мыши за пределами моего окна в Java

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

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

4b9b3361

Ответ 1

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

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

Вторая точка находится вне приложения.

Ответ 2

Забудьте о 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 getRgb(x,y), и все готово.

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

EDIT Я просто понял, что вам нужно выбрать несколько цветов, это сложнее, но все равно можно сделать с использованием 100% Java. Либо вы можете жить с "слегка выключенными" цветами (затронутыми "почти прозрачным" "невидимым" слоем), либо, получив щелчок, вы должны удалить слой, получить правильный пиксельный цвет и снова добавить "почти прозрачный" слой. Теперь, конечно, это одна черта взлома, но это можно сделать на 100% Java.

Ответ 3

Используйте

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

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

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

Ответ 5

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

Как уже было показано Keilly, возможно только выведение мыши.

Вам нужно включить родной lib

Ответ 6

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

Ответ 7

Расположение (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());
        }
    }
}

Ответ 8

У меня недостаточно комментариев, чтобы оставлять комментарии, но вот мои комментарии к другим методам:

  • Использовать собственный lib: будет работать, но имеет очевидные ограничения распространения

  • Используйте GlassPane для заполнения всего экрана: GlassPanes должен содержаться в окне.

  • Создайте окно, содержащее изображение рабочего стола и заполнив весь экран: будет работать, но он внезапно заставит рабочий стол статичным. Курсор больше не будет изменяться, любые анимации или видео в других окнах или на рабочем столе станут жутко статичными.

Альтернативное решение: Уточнение окна заполнения экрана, если вы используете Java 6u10 или новее, должно сделать окно полностью прозрачным. Поместите это окно перед всеми остальными и прислушайтесь к щелчкам мыши. У него все еще есть недостатки, такие как отсутствие изменений курсора, но это зависит от того, что вы хотите сделать.

Ответ 9

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

Ответ 10

Возможно с небольшим трюком. Должна быть 100% кросс-платформенная (протестирована на Linux и Windows). В принципе, вы создаете небольшой JWindow, делаете его "alwaysOnTop" и перемещаете его с помощью мыши с помощью таймера.

Подробнее см. в моем ответе here.

Ответ 11

Слушай, я понимаю, что я опаздываю на 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);

        }
    }
}