it-swarm.com.de

so erhalten Sie Mausklickkoordinaten außerhalb meines Fensters in Java

Ich muss eine Klasse mit Swing implementieren, die die Mauskoordinaten abrufen kann, wenn der Benutzer irgendwo auf den Bildschirm klickt. Wenn ich die Mauskoordinaten in meinem eigenen Fenster erhalten wollte, würde ich eine MouseListener verwenden, aber ich möchte, dass sie funktioniert, auch wenn der Benutzer außerhalb meines Programms klickt.

Ich möchte, dass sich meine Klasse genau wie KColorChooser verhält: Der Benutzer klickt auf die Drop-Schaltfläche und kann auf eine beliebige Stelle des Bildschirms klicken, um die Farbe dieser Stelle zu erhalten. aber ich weiß nicht, ob das mit reinem Java möglich ist.

17
cd1

Es ist möglich, wenn auch begrenzt: 

Fügen Sie einen AWTEventListener für Fokusereignisse hinzu. Solange Ihre App den Fokus hat, bevor auf die Schaltfläche geklickt wird, erhalten Sie ein Ereignis mit Fokusverlust. Fragen Sie dann nach der Zeigerposition.

Die Einschränkung ist, dass natürlich Ihre App den Fokus verliert. Abhängig davon, was Sie letztendlich erreichen wollen, ist dies möglicherweise nicht nützlich.

Wenn Sie den Fokus nicht verlieren möchten, müssen Sie vorübergehend einen Screenshot des gesamten Bildschirms erstellen und diesen in einem Bildschirmfüllfenster anzeigen, das wie gewohnt auf einen Mausklick wartet. 

Nachweis der ersten Methode:

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

Klicken außerhalb der erstellten App:

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

Der zweite Punkt liegt außerhalb der App.

23
Keilly

Wenn Sie GlassPane vergessen, gibt es eine weitere 100% native Java-Methode, die sowohl unter OS X als auch unter Windows funktioniert.

Java hat always unterstützte Transluzenz für seine Fenster unter OS X und Java unterstützt jetzt auch Transluzenz für seine Fenster unter Windows (da Java 1.6.0_10 oder so überprüft werden muss).

Der Trick ist also: Wenn Sie auf das Werkzeug "Wählen Sie eine Farbe" klicken, erstellen Sie ein nahezu transparentes, randloses Java-Fenster, das den gesamten Bildschirm abdeckt. Sie setzen das Alpha auf 10 (Alpha geht von 0 bis 255). Dieses Alpha ist so niedrig, dass der Benutzer nicht bemerken wird, dass es ein sehr dünnes "fast transparent, aber nur sehr, sehr durchscheinend" randloses Fenster gibt, das den gesamten Bildschirm abdeckt.

Wenn der Benutzer nun auf das gesamte Fenster "alpha set to 10 translucent borderless window" klickt, erhalten Sie Ihr (x, y).

Verwerfen Sie das randlose Java-Fenster.

Verwenden Sie RobotsgetRgb(x,y) und Sie sind fertig.

Warum das Alpha auf 10 und nicht auf 0 setzen? Denn sonst werden Klicks nicht von Java abgefangen, sondern direkt zum Betriebssystem geleitet (so funktioniert es zumindest unter OS X). Es gibt eine Schwelle und ich weiß, dass es nicht auf '1' oder '2' gesetzt ist, es ist ungefähr 10. 

EDITIch habe gerade gemerkt, dass Sie mehrere Farben auswählen müssen. Dies ist zwar komplizierter, kann aber trotzdem mit 100% Java ausgeführt werden. Entweder Sie können mit "etwas abgelassenen" Farben leben (betroffen von der "fast transparenten" "unsichtbaren" Ebene) oder Wenn Sie einen Klick erhalten, müssen Sie die Ebene entfernen, die korrekte Pixelfarbe erhalten und erneut eine "fast transparente" Schicht. Das ist natürlich ein Hacker, aber es kann in 100% Java gemacht werden.

19
SyntaxT3rr0r

Benutzen 

import Java.awt.MouseInfo;
import Java.awt.Point;
import Java.awt.PointerInfo;

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

p.x und p.y geben Ihnen Koordinaten außerhalb Ihres Fensters.

10
Chris

Ich weiß nicht, ob das mit Reinem Java möglich ist.

Mit reinem Java ist dies nicht möglich, da Java nur MouseEvents unter Windows kennt, die zu Java gehören.

4
camickr

Diese Ereignisse werden zu dem Fenster geleitet, das den Fokus hat. Von allen Ereignissen auf dem Desktop können Sie nur die Mausposition abrufen.

Wie bereits von Keilly gezeigt, ist es nur möglich, die Mausposition zu erhalten.

Sie müssen eine native lib einfügen.

4
stacker

Ich habe es selbst nicht ausprobiert, aber vielleicht könnten Sie ein transparentes Panel/Frame/etc im Vollbildmodus erstellen und einen MouseListener hinzufügen.

2
Chris

Der Ort (x, y) und das Zeitintervall (D) zwischen jedem Klick werden durch Befehlszeilenargumente angegeben. Hier ist das Programm

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());
        }
    }
}
1
selami

Mit einem kleinen Trick ist es möglich. Sollte zu 100% plattformübergreifend sein (getestet unter Linux und Windows). Grundsätzlich erstellen Sie ein kleines JWindow, machen es "alwaysOnTop" und bewegen Sie es mit der Maus mit einem Timer.

Für Details siehe meine Antwort hier .

0
Stefan Reich

Schau, ich verstehe, dass ich 7 Jahre zu spät komme ...

Dies ist eine Neuauflage von Keillys Antwort, die es ermöglicht, an jedem beliebigen Ort zu gelangen, wenn die Maustaste gedrückt wird. Das Hauptproblem ist, dass Vollbild-Spiele immer unscharf sind und es nervig wird, damit umzugehen.

Hier ist der Code:

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

Basierend auf der Antwort von SyntaxT3rr0r habe ich in Groovy einen Muster-Farbwähler erstellt, der zeigt, wie er funktionieren kann.

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()
    }
}
0
fuemf5

Ich habe noch nicht genug Vertreter, um Kommentare zu hinterlassen, aber hier sind meine Kommentare zu den anderen Techniken:

  • Verwenden Sie eine native lib: funktioniert, hat aber offensichtliche Einschränkungen bei der Verteilung

  • Verwenden Sie GlassPane, um den gesamten Bildschirm auszufüllen: GlassPanes muss in einem Fenster enthalten sein.

  • Erstellen Sie ein Fenster mit einem Bild des Desktops und füllen Sie den gesamten Bildschirm aus: Funktioniert, aber der Desktop wird plötzlich statisch. Der Cursor ändert sich nicht mehr, Animationen oder Videos in anderen Fenstern oder auf dem Desktop werden unheimlich statisch.

Alternative Lösung: Eine Verfeinerung des Bildschirmfüllfensters, wenn Sie Java 6u10 oder höher verwenden, besteht darin, das Fenster vollständig transparent zu machen. Setzen Sie dieses Fenster vor alle anderen und hören Sie auf Mausklicks. Es hat immer noch Mängel, z. B. keine Cursoränderungen, aber es hängt davon ab, was Sie tun möchten.

0
Keilly