I want my app to detect mouse clicks anywhere on the screen without having to have the app focused. I want it to detect mouse events universally even if its minimized. So far I've only been able to detect mouse events within a swing gui.
Autohotkey can detect mouse clicks and get the mouse's position at any time, how can I do this with java?
It is possible with a little trick. Should be 100% cross-platform (tested on Linux & Windows). Basically, you create a small JWindow, make it "alwaysOnTop" and move it around with the mouse using a timer.
Then, you can record the click, dismiss the window and forward the click to the actual receiver using the Robot class.
Short left and right clicks work completely fine in my tests.
You could also simulate dragging and click-and-hold, just forwarding that seems harder.
I have code for this, but it is in my Java extension (JavaX). JavaX does translate into Java source code, so you can check out the example here.
The code in JavaX:
static int windowSize = 11; // odd should look nice. Set to 1 for an invisible window
static int clickDelay = 0; // Delay in ms between closing window and forwarding click. 0 seems to work fine.
static int trackingSpeed = 10; // How often to move the window (ms)
p {
final new JWindow window;
window.setSize(windowSize, windowSize);
window.setVisible(true);
window.setAlwaysOnTop(true);
JPanel panel = singleColorPanel(Color.red);
window.setContentPane(panel);
revalidate(window);
final new Robot robot;
panel.addMouseListener(new MouseAdapter {
// public void mousePressed(final MouseEvent e) {}
public void mouseReleased(final MouseEvent e) {
print("release! " + e);
window.setVisible(false);
int b = e.getButton();
final int mod =
b == 1 ? InputEvent.BUTTON1_DOWN_MASK
: b == 2 ? InputEvent.BUTTON2_DOWN_MASK
: InputEvent.BUTTON3_DOWN_MASK;
swingLater(clickDelay, r {
print("clicking " + mod);
robot.mousePress(mod);
robot.mouseRelease(mod);
});
}
});
swingEvery(window, trackingSpeed, r {
Point p = getMouseLocation();
window.setLocation(p.x-windowSize/2, p.y-windowSize/2);
//print("moving");
});
}
Related
I am developing a Java application where when a button in the GUI is pressed, the user can click anywhere on the screen to record the x and y coordinates where they clicked.This is done by putting an undecorated, partly transparent JFrame over the entire screen that listens for a mouse click, records the x/y coords, then closes itself upon being clicked.
Transparent JFrame class (note: extends JFrame)
setUndecorated(true);
setOpacity((float) 0.75);
W = Toolkit.getDefaultToolkit().getScreenSize().width;
H = Toolkit.getDefaultToolkit().getScreenSize().height;
setSize(W,H);
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
X = e.getX();
Y = e.getY();
System.out.println(X + ":" + Y);
closed = true;
dispose();
}
});
}
public void start() {
java.awt.EventQueue.invokeLater(() -> {
this.setVisible(true);
});
}
public boolean closed = false;
public int X = -1;
public int Y = -1;
method from button press (note: extends JFrame)
setVisible(false);
click_frame.start();
while(!click_frame.closed) {
}
setVisible(true);
System.out.println(click_frame.X + "," + click_frame.Y);
The problem I am having is that the while loop hangs the entire application not just the main GUI. I want to use wait() and notifyAll() because I am trying to intentionally hang the main GUI until click_frame.X and click_frame.Y have values.
When I tried other methods without the while loop, the "click_frame JFrame class" ran alongside the main GUI, instead of blocking it, which is not what I want to happen.
My question is how can I make the main GUI use wait()/notifyAll() so it will stop while the second JFrame records the input.
Swing is a single threaded framework, this means that any long running or blocking process which is executed within the context of the Event Dispatching Thread, will prevent the framework from responding to new events
My question is how can I make the main GUI use wait()/notifyAll() so it will stop while the second JFrame records the input.
Don't. Swing, like most UI frameworks is event driven, this means, something happens (at some point in time) and you respond to it.
Instead, simply make use of a MouseListener and monitor the mouseClicked event. When it occurs, you can use the MouseEvent#getLocationOnScreen method to determine where on the screen the user clicked.
When clicked, this should then report back to the caller (via some kind of observer pattern) the results of the call.
Of course, you could cheat and simply use a modal JDialog, which will block (safely) at the point the dialog is made visible, until it is dismissed (closed)
This question already has answers here:
how to obtain mouse click coordinates outside my window in Java
(12 answers)
Closed 8 years ago.
I am learning java as a beginner and I was tasked to make an auto-click tool. I used JFrame as an Interface but now I'm stuck with this problem:
- I want to get location of pointer related to screen after user clicked a button (Ctrl for example). I added a button on JFrame, click it and the JFrame will be minimized so user can move the pointer around desktop.
- Whenever user pressed Ctrl key, I should println the x,y position of the pointer at that time.
- I've been swum around to find a solution, but it seemed like my brain couldn't catch up.
It would be a very appreciation if anyone can provide me a simple example. Thanks.
My idea so far:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
this.setState(JFrame.ICONIFIED);
this.addKeyListener(this);
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.CTRL_DOWN_MASK) {
PointerInfo a = MouseInfo.getPointerInfo();
Point b = a.getLocation();
int x = (int) b.getX();
int y = (int) b.getY();
System.out.println(x + ":" + y);
}
}
I want to get location of pointer related to screen after user clicked a button..
On button click:
Hide the frame.
Get a screenshot of the entire desktop.
Show the screenshot in a JLabel in a JWindow
Add a MouseListener to the label.
Get the Point from the MouseEvent.
E.G. similar to what is shown in this answer.
I'd like to simulate a Mouse click on a Graphic. I added a Mouselistener, and some action when the mouseclick is done, but I really need to simulate that the user clicked on my Graphic in my programm... How can I say something like "" MouseEvent e is performed!"" ?
Actually I'd like to clean a "Graphics 2D canvas" when you click on a Jbutton called "Clean". But the thing is that the cleaning action would be done only if the user click on my "Graphics 2D canvas". I'd like to make the illusion that the "Graphics 2D canvas" was cleaned by clicking on the JButton..
Thanks.
addMouseListener(this);
addMouseMotionListener(this);
public void mousePressed(MouseEvent e) {
e.consume();
x1=e.getX();
y1=e.getY();
if(figure==1 || figure==3 ) {x2=x1; y2=y1;}
; }
PS : I can't use robot because I have to run my programm on every OS, and someone told me I can't run this on every programm :
Robot robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// SET THE MOUSE X Y POSITION
robot.mouseMove(65*Fond_noir.pourcent_largeur, 16*Fond_noir.pourcent_hauteur);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
}
Well, you're right about Robot. It's platform dependent, and there are no guarantees that it will support all features on all platforms, from the JavaDoc:
Note that some platforms require special privileges or extensions to
access low-level input control. If the current platform configuration
does not allow input control, an AWTException will be thrown when
trying to construct Robot objects. For example, X-Window systems will
throw the exception if the XTEST 2.2 standard extension is not
supported (or not enabled) by the X server.
To simulate the click, you can simply do this:
JButton buttonToSimulateClicking = new JButton(...);
buttonToSimulateClicking.doClick(); // As simple as that !
If you have to simulate the click "the hard way", i.e. to simulate a mouse click, you can always do the following:
MouseEvent clickEvent = new MouseEvent(buttonToSimulateClicking, MouseEvent.MOUSE_CLICKED, ...);
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
eventQueue.dispatchEvent(clickEvent);
Is there any way to get mouse coordinates on a click of desktop screen, i dont want to click inside the java frame, want to click the mouse pointer straight away on desktop and have to know the x,y coordinates ? please help me out? (windows)
Rectangle rectScreenSize = new Rectangle(x1,y1,x2,y2);
BufferedImage biScreen = robot.createScreenCapture (rectScreenSize);
finally want to pass the coordinates for rectangle, to determine the screen size for robot class?
You can make a transparent, undecorated JFrame on top of everything, and pass the click on with the Robot class.
By the way, the following does not work outside your own window (I had hoped so):
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
System.out.println("event: " + event);
if (event.toString().contains("MOUSE_EXITED")) {
System.out.println("mouse_exited");
}
}
}, AWTEvent.MOUSE_EVENT_MASK);
Suppose I have 4 squares colored blue, white, red and green (myComponent) associated with the mouse press event. At one point, the mouse is pressed over one of them - say, the yellow one - and the event is activated.
Now, the control flux is inside the event handling function. How do I get the MyComponent - the yellow square - that caused this from here?
EDIT
I have another question. Is there a way to tell the position of the component? My problem is a bit more complicated than what I said.
Basically, I have a grid full of squares. When I click one of the squares, I have to know which one it is, so I can update my matrix. The thing is, if I calculate it myself, it only works on a given resolution.
I have a GridBagLayout, and inside it are the myComponents. I have to know which one of the components exactly - like, component[2][2] - caused the interruption.
I mean, I can tell which one of the components did it, but not where in the matrix it is located.
MouseEvent.getSource() returns the object on which the event initially occurred.
I have a GridBagLayout, and inside it
are the myComponents. I have to know
which one of the components exactly -
like, component[2][2] - caused the
interruption.
You could store the indices, e.g. (2,2), inside each myComponent when you add them to the matrix. That way, given the component, you can always identify its position in the matrix.
class MyComponent extends JButton
{
final int i; // matrix row
final int j; // matrix col
// constructor
MyComponent(String text, int i, int j)
{
super(text);
this.i = i;
this.j = j;
}
...
}
By adding a MouseListener (or alternatively, a MouseAdapter, if you don't need to override all the MouseListener' methods) to each of your colored boxes, when an event such as a mouse click occurs, theMouseListenerwill be called with a [MouseEvent`]3, which can be used to obtain the component that was clicked.
For example:
final MyBoxComponent blueBox = // ... Initialize blue box
final MyBoxComponent whiteBox = // ... Initialize white box
final MyBoxComponent redBox = // ... Initialize red box
final MyBoxComponent greenBox = // ... Initialize green box
MouseListener myListener = new MouseAdapter() {
public void mouseClicked(MouseEvent e)
{
// Obtain the Object which caused the event.
Object source = e.getSource();
if (source == blueBox)
{
System.out.println("Blue box clicked");
}
else if (source == whiteBox)
{
System.out.println("White box clicked");
}
// ... and so on.
}
};
blueBox.addMouseListener(myListener);
whiteBox.addMouseListener(myListener);
redBox.addMouseListener(myListener);
greenBox.addMouseListener(myListener);