J'ai besoin d'implémenter une classe, en utilisant Swing, qui peut obtenir les coordonnées de la souris lorsque l'utilisateur clique n'importe où sur l'écran. si je voulais obtenir les coordonnées de la souris à l'intérieur de ma propre fenêtre, j'utiliserais une MouseListener
, mais je souhaite que cela fonctionne même lorsque l'utilisateur clique en dehors de mon programme.
Je veux que ma classe se comporte comme KColorChooser : l'utilisateur clique sur le bouton de la liste déroulante et peut cliquer n'importe où sur l'écran pour obtenir la couleur de cet endroit. mais je ne sais pas si cela est possible avec Java pur.
C'est possible quoique limité:
Ajoutez un AWTEventListener pour les événements de focus. Tant que votre application a le focus avant que le bouton ne soit cliqué, vous recevez un événement de perte de focus. Ensuite, recherchez la position du pointeur.
La limitation est que, bien sûr, votre application perd le focus. Donc, selon ce que vous essayez en fin de compte de réaliser, cela pourrait ne pas être utile.
Si vous ne voulez pas perdre la mise au point, vous devrez temporairement prendre une capture d'écran de tout l'écran et l'afficher dans une fenêtre de remplissage d'écran à l'écoute d'un clic de souris, comme d'habitude.
Preuve de la première méthode:
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);
}
}
}
En cliquant en dehors de l'application produite:
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, ...
Le deuxième point est en dehors de l'application.
Oubliez GlassPane
, il existe un autre moyen de le faire en Java 100% naturel qui fonctionne aussi bien sous OS X que sous Windows.
Java a une transparence de toujours prise en charge pour ses fenêtres sous OS X et Java prend désormais également en charge la translucidité de ses fenêtres sous Windows (à partir de la version 1.6.0_10 de Java, elle doit être vérifiée).
Le truc est donc le suivant: en cliquant sur l'outil "choisir une couleur", vous créez une fenêtre Java presque transparente et sans bordure couvrant la totalité de l'écran. Vous définissez sa valeur alpha sur 10 (la valeur alpha va de 0 à 255). Cette valeur alpha est si faible que l’utilisateur ne remarquera pas qu’il existe une très mince "presque transparente mais seulement très très très translucide" _ fenêtre sans bordure couvrant la totalité de l’écran.
Désormais, lorsque l'utilisateur clique sur votre "alpha réglé sur 10 fenêtres sans bordure translucides" couvrant la totalité de l'écran, vous obtenez votre (x, y).
Jeter la fenêtre Java sans frontières.
Utilisez la fonction Robot
's getRgb(x,y)
et vous avez terminé.
Pourquoi régler l’alpha sur 10 et non sur 0? Parce que sinon, les clics ne sont pas interceptés par Java mais vont directement au système d'exploitation (du moins, c'est comme ça que ça fonctionne pour OS X). Il y a un seuil et je sais qu'il n'est pas fixé à '1', ni à '2', il se situe autour de 10 ou plus.
EDITJe viens de réaliser que vous savez qu'il faut choisir plusieurs couleurs. C'est plus compliqué, mais vous pouvez toujours le faire en utilisant 100% Java. Soit vous pouvez vivre avec des couleurs "légèrement décollées" (affectées par le calque "invisible" "presque transparent") ou après avoir cliqué, vous devez supprimer le calque, obtenir la couleur de pixel correcte et replacer une couche "presque transparente". Bien sûr, c’est un sacré bidouillage, mais cela peut se faire en Java à 100%.
Utilisation
import Java.awt.MouseInfo;
import Java.awt.Point;
import Java.awt.PointerInfo;
PointerInfo inf = MouseInfo.getPointerInfo();
Point p = inf.getLocation();
p.x et p.y vous donneront des coordonnées en dehors de votre fenêtre.
Je ne sais pas si cela est possible avec Java pur.
Ce n'est pas possible avec Java pur, car Java ne connaît que MouseEvents sous Windows appartenant à Java.
Ces événements sont dirigés vers la fenêtre qui a le focus, à partir de tous les événements sur le bureau, vous ne pouvez obtenir que la position de la souris.
Comme Keilly l'a déjà montré, il est seulement possible d'obtenir la position de la souris.
Vous devez inclure un native lib
Je n'ai pas essayé cela moi-même, mais vous pourriez peut-être créer un panneau/cadre/etc transparent en plein écran et ajouter un MouseListener à cela.
L'emplacement (x, y) et l'intervalle de temps (D) entre chaque clic sont fournis via des arguments de ligne de commande. Voici le programme
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());
}
}
}
C'est possible avec un petit truc. Devrait être 100% multi-plateforme (testé sur Linux et Windows). Fondamentalement, vous créez une petite JWindow, faites-la "alwaysOnTop" et déplacez-la avec la souris à l'aide d'une minuterie.
Pour plus de détails, voir ma réponse ici .
Ecoute, je comprends que j'ai 7 ans de retard ...
Ceci est une refonte de la réponse de Keilly, qui permet d'obtenir lorsque le bouton de la souris est cliqué, n'importe où. Le problème principal est que les jeux en plein écran sont toujours flous et que cela devient ennuyeux à gérer.
Voici le 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);
}
}
}
Sur la base de la réponse de SyntaxT3rr0r , j'ai créé un exemple de sélecteur de couleur dans Groovy qui montre comment cela peut fonctionner.
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()
}
}
Je n'ai pas encore assez de représentants pour laisser des commentaires, mais voici mes commentaires sur les autres techniques:
Utiliser une bibliothèque native: fonctionnera, mais a des limitations de distribution évidentes
Utilisez GlassPane pour remplir tout l’écran: Les GlassPanes doivent être contenus dans une fenêtre.
Créez une fenêtre contenant une image du bureau et remplissez tout l'écran: Cela fonctionnera, mais le bureau deviendra soudainement statique. Le curseur ne changera plus, les animations ou vidéos dans d'autres fenêtres ou bureaux deviendront étrangement statiques.
Solution alternative: Si vous utilisez Java 6u10 ou une version ultérieure, si vous utilisez Java 6u10 ou une version ultérieure, la fenêtre complètement transparente . Placez cette fenêtre devant tous les autres et écoutez les clics de souris. Il y a toujours des inconvénients, tels qu’aucun changement de curseur, mais cela dépend de ce que vous voulez faire.