web-dev-qa-db-ja.com

Javaでウィンドウの外のマウスクリック座標を取得する方法

Swingを使用して、ユーザーが画面上の任意の場所をクリックしたときにマウスの座標を取得できるクラスを実装する必要があります。自分のウィンドウ内でマウスの座標を取得したい場合は、MouseListenerを使用しますが、ユーザーがプログラムの外側をクリックしても機能します。

クラスを KColorChooser のように動作させたい:ユーザーがドロップボタンをクリックすると、画面上の任意の場所をクリックしてそのスポットの色を取得できます。しかし、純粋なJavaを使用してそれが可能かどうかはわかりません。

19
cd1

制限はありますが可能です:

フォーカスイベントの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番目のポイントは、アプリの外です。

24
Keilly

GlassPaneを忘れてください。OSXとWindowsの両方で機能する、別の100%ネイティブJava方法があります。

JavaはalwaysOS X上のウィンドウの透過性をサポートし、JavaはWindows上のウィンドウの透過性もサポートするようになりました( Java 1.6.0_10などなので、確認する必要があります)。

だからトリックは:「色を選ぶ」ツールをクリックすると、ほぼ透明なボーダーレスを作成しますJava画面全体を覆うウィンドウ。アルファを10に設定します(アルファは0から255になります)。このアルファは非常に低いため、ユーザーは非常に薄いに気づかないでしょうが、ほぼ透明ですが画面全体を覆う非常に非常に非常に非常に半透明な "ボーダーレスウィンドウ。

ユーザーが画面全体をカバーする「アルファを10半透明のボーダーレスウィンドウに設定」をクリックすると、(x、y)が表示されます。

ボーダレスJavaウィンドウを破棄します。

RobotgetRgb(x,y)を使用すれば完了です。

アルファを0ではなく10に設定する理由それ以外の場合、クリックはJava=によってインターセプトされませんが、OSに直接移動します(少なくとも、OS Xのファクトに対してそれがどのように機能するかです)。しきい値があり、 ' 1 'でも' 2 'でもない、約10程度です。

[〜#〜] edit [〜#〜]いくつかの色を選択する必要があることがわかったので、これはトリッキーですが、100%Javaを使用しても実行できます。 「わずかにオフ」の色(「ほぼ透明」の「非表示」レイヤーの影響を受ける)またはのどちらでもかまいませんが、クリックすると、レイヤー、正しいピクセルカラーを取得し、「ほぼ透明な」レイヤーを再度配置します。もちろん、これはハックの1つですが、100%Javaで実行できます。

21
SyntaxT3rr0r

使用する

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

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

p.xとp.yは、ウィンドウ外の座標を提供します。

11
Chris

純粋なJavaを使用してそれが可能かどうかはわかりません。

Javaは、Javaに属するWindowsのMouseEventsのみを認識しているため、純粋なJavaを使用することはできません。

4
camickr

これらのイベントは、フォーカスがあるウィンドウに送信されます。デスクトップ上のすべてのイベントから、マウスの位置のみを取得できます。

Keillyがすでに示したように、マウスの位置を取得することのみが可能です。

native lib を含める必要があります

4
stacker

私はこれを自分で試したことはありませんが、フルスクリーンの透明なパネル/フレームなどを作成し、それにMouseListenerを追加できます。

2
Chris

ちょっとしたトリックで可能です。 100%クロスプラットフォームである必要があります(LinuxおよびWindowsでテスト済み)。基本的には、小さなJWindowを作成して「alwaysOnTop」にし、タイマーを使用してマウスで移動します。

詳細については、私の回答 こちら を参照してください。

1
Stefan Reich

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

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

コメントを残すのに十分な担当者がいませんが、他のテクニックについてのコメントは次のとおりです。

  • ネイティブlibを使用:機能しますが、明らかな配布上の制限があります

  • GlassPaneを使用して画面全体を埋める:GlassPanesはウィンドウ内に含まれている必要があります。

  • デスクトップの画像を含むウィンドウを作成し、画面全体に表示します。動作しますが、突然デスクトップが静的になります。カーソルは変更されなくなり、他のウィンドウやデスクトップのアニメーションやビデオは不気味に静的になります。

別の解決策:Java 6u10以降を使用している場合は、画面いっぱいのウィンドウを改良して、ウィンドウを 完全に透明にする にします。このウィンドウをすべての前面に置きます。カーソルの変更がないなどの欠点はまだありますが、それは何をしたいかによって異なります。

0
Keilly