tipos - Cómo obtener las coordenadas del clic del ratón fuera de mi ventana en Java
jframe en java pdf (11)
No sé si eso es posible usando Java puro.
No es posible usar Java puro, ya que Java solo es consciente de MouseEvents en Windows que pertenece a Java.
Necesito implementar una clase, usando Swing, que puede obtener las coordenadas del mouse cuando el usuario hace clic en cualquier lugar de la pantalla. si quisiera obtener las coordenadas del mouse dentro de mi propia ventana, usaría un MouseListener
, pero quiero que funcione incluso cuando el usuario hace clic fuera de mi programa.
Quiero que mi clase se comporte como KColorChooser : el usuario hace clic en el botón de soltar y puede hacer clic en cualquier parte de la pantalla para obtener el color de ese lugar. pero no sé si eso es posible usando Java puro.
Basándome en la respuesta de SyntaxT3rr0r , creé un selector de color de muestra en groovy que muestra cómo puede funcionar.
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()
}
}
Es posible aunque limitado:
Agregue un AWTEventListener para eventos de enfoque. Siempre que su aplicación tenga un enfoque antes de hacer clic en el botón, recibirá un evento de pérdida de enfoque. A continuación, consulte la posición del puntero.
La limitación es que, por supuesto, tu aplicación pierde el enfoque. Por lo tanto, dependiendo de lo que esté intentando lograr en última instancia, esto podría no ser útil.
Si no desea perder el enfoque, tendrá que tomar temporalmente una captura de pantalla de toda la pantalla y mostrarla en una ventana de relleno de pantalla que escucha el clic del mouse como de costumbre.
Prueba del primer método:
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);
}
}
}
Haciendo clic fuera de la aplicación producida:
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, ...
El segundo punto está fuera de la aplicación.
Es posible con un pequeño truco. Debería ser 100% multiplataforma (probado en Linux y Windows). Básicamente, creas una JWindow pequeña, la haces "alwaysOnTop" y la mueves con el mouse usando un temporizador.
Para más detalles, vea mi respuesta here .
Estos eventos se dirigen a la ventana que tiene el foco, de todos los eventos en el escritorio solo puede obtener la posición del mouse.
Como ya mostró Keilly, solo es posible obtener la posición del mouse.
Necesitas incluir un lib nativo
La ubicación (x, y) y el intervalo de tiempo (d) entre cada clic se suministran a través de los argumentos de la línea de comando. Aquí está el programa
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());
}
}
}
Mira, entiendo que tengo 7 años de retraso ...
Esta es una nueva versión de la respuesta de Keilly, que permite obtenerla cuando se hace clic en el botón del mouse, en cualquier lugar. El problema principal es que los juegos de pantalla completa siempre están desenfocados y su manejo se vuelve molesto.
Aquí está el código:
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);
}
}
}
No lo he intentado yo mismo, pero quizás pueda crear un panel / marco / etc transparente de pantalla completa y agregar un MouseListener a eso.
Olvídese de GlassPane
, hay otra forma 100% nativa de hacerlo que funciona tanto en OS X como en Windows.
Java siempre ha admitido la translucidez para sus ventanas en OS X y Java ahora también es compatible con sus ventanas en Windows (desde Java 1.6.0_10 o algo así, debe comprobarse).
Así que el truco es: al hacer clic en la herramienta "elegir un color" , crea una ventana de Java casi transparente sin bordes que cubre toda la pantalla. Establece su alfa en 10 (alfa va de 0 a 255). Ese alfa es tan bajo que el usuario no se dará cuenta de que hay una ventana sin bordes muy delgada "casi transparente pero solo muy, muy translúcida" que cubre toda la pantalla.
Ahora, cuando el usuario hace clic en su "ventana alfa configurada en 10 translúcidas sin bordes" que cubre toda la pantalla, obtiene su (x, y).
Deseche la ventana de Java sin bordes.
Use getRgb(x,y)
Robot
y listo.
¿Por qué configurar el alfa a 10 y no a 0? Porque de lo contrario, los clics no son interceptados por Java, sino que van directamente al sistema operativo (al menos así es como funciona para un hecho en OS X). Hay un umbral y sé que no está establecido en ''1'', ni en ''2'', es alrededor de 10 o menos.
EDITAR Me acabo de dar cuenta de que necesita elegir varios colores, esto es más complicado, pero aún se puede hacer usando 100% Java. Puede vivir con colores "ligeramente apagados" (afectados por la capa "casi transparente" "invisible") o al hacer clic, debe eliminar la capa, obtener el color de píxel correcto y volver a colocar una capa "casi transparente". Ahora, por supuesto, es un gran truco, pero se puede hacer en 100% Java.
Todavía no tengo suficiente reputación para dejar comentarios, pero aquí están mis comentarios sobre las otras técnicas:
Use una biblioteca nativa: funcionará, pero tiene limitaciones de distribución obvias
Use GlassPane para llenar toda la pantalla: GlassPanes debe estar contenido dentro de una ventana.
Cree una ventana que contenga una imagen del escritorio y llene toda la pantalla: funcionará, pero de repente hará que el escritorio sea estático. El cursor ya no cambiará, cualquier animación o video en otras ventanas o escritorio se volverá inquietantemente estático.
Solución alternativa: un refinamiento de la ventana de relleno de la pantalla, si está utilizando Java 6u10 o posterior, es hacer que la ventana sea completamente transparente . Coloque esta ventana delante de todas las demás y escuche los clics del mouse. Todavía tiene defectos, como no hay cambios de cursor, pero depende de lo que quieras hacer.
Utilizar
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
PointerInfo inf = MouseInfo.getPointerInfo();
Point p = inf.getLocation();
px y py te darán coordenadas fuera de tu ventana.