我需要使用Swing实现一个类,用于在用户单击屏幕上任何位置时获取鼠标坐标。如果我想要获取自己窗口内的鼠标坐标,我会使用MouseListener
,但我希望它即使在用户单击程序外部也能起作用。
我希望我的类的行为就像KColorChooser:用户单击下拉按钮后,可以单击屏幕上任何位置以获取该点的颜色。但我不知道是否可以使用纯Java实现。
我需要使用Swing实现一个类,用于在用户单击屏幕上任何位置时获取鼠标坐标。如果我想要获取自己窗口内的鼠标坐标,我会使用MouseListener
,但我希望它即使在用户单击程序外部也能起作用。
我希望我的类的行为就像KColorChooser:用户单击下拉按钮后,可以单击屏幕上任何位置以获取该点的颜色。但我不知道是否可以使用纯Java实现。
基于 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()
}
}
我还没有足够的声望来留下评论,但这是我对其他技术的评论:
使用本地库:可以工作,但有明显的分发限制。
使用GlassPane填充整个屏幕:GlassPanes必须包含在一个窗口中。
创建一个包含桌面图片并填充整个屏幕的窗口:可以工作,但会使桌面突然变得静态。光标将不再改变,在其他窗口或桌面中的任何动画或视频都将变得异常静态。
替代方案: 如果您使用的是Java 6u10或更高版本,则可以对屏幕填充窗口进行细化,使其完全透明。将此窗口放在所有其他窗口前面并监听鼠标点击。它仍然有缺点,例如没有光标更改,但这取决于您想要做什么。