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

25

我需要使用Swing实现一个类,用于在用户单击屏幕上任何位置时获取鼠标坐标。如果我想要获取自己窗口内的鼠标坐标,我会使用MouseListener,但我希望它即使在用户单击程序外部也能起作用。

我希望我的类的行为就像KColorChooser:用户单击下拉按钮后,可以单击屏幕上任何位置以获取该点的颜色。但我不知道是否可以使用纯Java实现。

12个回答

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

0

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

  • 使用本地库:可以工作,但有明显的分发限制。

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

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

替代方案: 如果您使用的是Java 6u10或更高版本,则可以对屏幕填充窗口进行细化,使其完全透明。将此窗口放在所有其他窗口前面并监听鼠标点击。它仍然有缺点,例如没有光标更改,但这取决于您想要做什么。


看起来WizardOfOdds也有相同的关于半透明窗口的想法。但要记住,它们的实现因平台而异,每个平台都有各种限制,正如他在OSX上演示的那样,并且实际上不能保证在所有平台上运行。尽管如此,看起来我们已经发现了一些不同的技术可以尝试。 - Keilly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接