How to Simulate a Real Mouse Click Using Java

Simulate left click in java?

I suggest you to check for documentation, it's available.
here
and here
here is an example of how to use robot

    try{

Robot robot = new Robot();
// mouse move
robot.mouseMove(x,y);// x,y are cordinates
// Simulate a mouse click
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);

// Simulate a key press
robot.keyPress(KeyEvent.VK_A);
robot.keyRelease(KeyEvent.VK_A);

} catch (AWTException e) {
e.printStackTrace();
}

Getting input from String to simulate mouse clicks

Firstly:

The program is to take a 2 letter input,

Your program takes a letter and a number as opposed to two letters, you need to be careful how you phrase things like that as it could affect how someone tries to deal with the solution, no biggy though
:)

Secondly: No idea if this is the best way but you could potentially create an ArrayList of your grid squares names (a1, a2, a3 e.t.c), then when you recieve input from the user iterate over the list until the input matches an entry in the ArrayList, once found either use robot to create the click, or manually fire an onClickEvent to a listener. If you find no entry on the list matching the user input then return an error citing invalid reference.

Also, to avoid manually entering each grid reference to the array one at a time, try using char ASCII values, and looping to create the list, similar to below:

    char c = 97;
char n = 49;
String s = Character.toString(c) + Character.toString(n);
System.out.println(s);

myArrray.add(s);

By successfully looping the above in the right way you will save adding each grid reference one by one.

Simulate a mouse click within Board (JPanel)

I'd like to give you an example on how to do it like I suggested in the comments. ("Why don't you just add a MouseListener for every cell", "You don't need a robot class") Of course you don't have to do it this way, but I think it is just easier to code & to understand. Right now the computer just picks random cells and there's no restart/win/lose, I just wanted to show you the concept. I wouldn't use the robot class in this case, the program shouldn't be able to take control over the cursor ;)

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.LineBorder;

public class TicTacToe {

Cell[][] cells = new Cell[3][3];
boolean humanTurn = true;

public TicTacToe() {

JFrame frame = new JFrame("T I C - T A C - T O E");

JPanel panel = new JPanel(new GridLayout(3, 3));
addCells(panel);

frame.add(panel);

frame.setSize(600, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);

ActionListener actionListener = new ActionListener() {

Random r = new Random();

@Override
public void actionPerformed(ActionEvent e) {

if (!humanTurn) {
// Random cell
int x = r.nextInt(3);
int y = r.nextInt(3);
Cell cell = cells[x][y];

if (!cell.clicked) {

// Only the computer runs the gameloop, so false
cell.human = false;
cell.cross = false;

cell.repaint();

// Make sure the panel repaints before setting next
// booleans
EventQueue.invokeLater(new Runnable() {
public void run() {
humanTurn = true;
cell.clicked = true;
}
});
}
}

}
};
Timer gameloop = new Timer(10, actionListener);
gameloop.start();

}

private void addCells(JPanel panel) {

for (int y = 0; y < 3; y++) {
for (int x = 0; x < 3; x++) {

Cell cell = new Cell();
cell.setBorder(new LineBorder(Color.BLACK));

cells[x][y] = cell;

panel.add(cell);

}
}
}

public static void main(String[] args) {

EventQueue.invokeLater(new Runnable() {
public void run() {
new TicTacToe();
}
});

}

class Cell extends JPanel implements MouseListener {

boolean clicked = false;
boolean human = true;
boolean cross = false;

public Cell() {

addMouseListener(this);

}

@Override
public void paintComponent(Graphics g) {

super.paintComponent(g);

Graphics2D gg = (Graphics2D) g;

// Makes drawing smooth
gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

// Drawing blue cross (player)
if (human && cross) {
gg.setColor(Color.BLUE);
gg.drawLine(20, 20, getWidth() - 20, getHeight() - 20);
gg.drawLine(getWidth() - 20, 20, 20, getHeight() - 20);
}

// Drawing red circle (computer)
else if (!human && !cross) {
gg.setColor(Color.RED);
gg.drawOval(10, 10, getWidth() - 20, getHeight() - 20);
}

}

@Override
public void mouseClicked(MouseEvent arg0) {

if (humanTurn && !clicked) {

// Only human can click on the panel, so true
human = true;
cross = true;

repaint();

// Make sure the panel repaints before setting next booleans
EventQueue.invokeLater(new Runnable() {
public void run() {
humanTurn = false;
clicked = true;
}
});

}

}

@Override
public void mouseEntered(MouseEvent arg0) {

}

@Override
public void mouseExited(MouseEvent arg0) {

}

@Override
public void mousePressed(MouseEvent arg0) {

}

@Override
public void mouseReleased(MouseEvent arg0) {

}

}

}

JNA / WinAPI. Simulating mouse click moves mouse cursor and doesn't return it back to the start position

The next presses of the Q button have more distance between clicked point and current mouse position and this distance differs after first pressing Q button.

The documentation already explains this:

Relative mouse motion is subject to the effects of the mouse speed and
the two-mouse threshold values. A user sets these three values with
the Pointer Speed slider of the Control Panel's Mouse Properties
sheet. You can obtain and set these values using the
SystemParametersInfo function.

The system applies two tests to the specified relative mouse movement.
If the specified distance along either the x or y axis is greater than
the first mouse threshold value, and the mouse speed is not zero, the
system doubles the distance. If the specified distance along either
the x or y axis is greater than the second mouse threshold value, and
the mouse speed is equal to two, the system doubles the distance that
resulted from applying the first threshold test. It is thus possible
for the system to multiply specified relative mouse movement along the
x or y axis by up to four times.

You can use absolute coordinates to complete the project.

If MOUSEEVENTF_ABSOLUTE value is specified, dx and dy contain
normalized absolute coordinates between 0 and 65,535. The event
procedure maps these coordinates onto the display surface. Coordinate
(0,0) maps onto the upper-left corner of the display surface;
coordinate (65535,65535) maps onto the lower-right corner. In a
multimonitor system, the coordinates map to the primary monitor.

Part of the code:

UINT mouseAction(int x, int y, int flags)
{
INPUT input;
POINT pos;
GetCursorPos(&pos);

input.type = INPUT_MOUSE;
input.mi.dwFlags = flags;
input.mi.time = NULL;
input.mi.mouseData = NULL;
input.mi.dx = (pos.x + x)*(65536.0f / GetSystemMetrics(SM_CXSCREEN));
input.mi.dy = (pos.y + y)*(65536.0f / GetSystemMetrics(SM_CYSCREEN));
input.mi.dwExtraInfo = GetMessageExtraInfo();

return SendInput(1, &input, sizeof(INPUT));
}

void mouseMove(int x, int y)
{
mouseAction(x, y, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
}

The code is C++, I am not familiar with JAVA code, but I think it is easy enough for you to change to Java.

Supplement: You can use GetAsyncKeyState to detect whether the Q key is pressed. Too many dependent hooks will affect operation performance.

As you may see cursor doesn't move back to the start position after first time pressing Q button.

You can save the starting coordinates. Then return to the starting position when needed.

Gif demo:

1

Updated:

To further help you solve the problem, I will demonstrate some operations for your reference.

Sample Image

We use GetCursorPos to get the coordinates of ABC.

A(267,337) B(508,334) C(714,329)

Then pass their coordinates to the input structure, refer to the following code:

#include <Windows.h>
#include <iostream>

UINT mouseAction(int x, int y, int flags)
{
INPUT input;
POINT pos;
int x1 = GetSystemMetrics(SM_CXSCREEN);
int y1 = GetSystemMetrics(SM_CYSCREEN);
input.type = INPUT_MOUSE;
input.mi.dwFlags = flags;
input.mi.time = NULL;
input.mi.mouseData = NULL;
input.mi.dx = x* (65536.0f / GetSystemMetrics(SM_CXSCREEN));
input.mi.dy = y* (65536.0f / GetSystemMetrics(SM_CYSCREEN));
input.mi.dwExtraInfo = GetMessageExtraInfo();

return SendInput(1, &input, sizeof(INPUT));
}

int main()
{
while(1)
{
if (GetAsyncKeyState(0x51) & 0x0001)
{
mouseAction(267, 337, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
}
if (GetAsyncKeyState(0x57) & 0x0001)
{
mouseAction(508, 334, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
}
if (GetAsyncKeyState(0x45) & 0x0001)
{
mouseAction(714, 329, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
// mouseAction(267-87, 337-65, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE);
}
}

return 0;
}

Although it is C++ code, the basic logic is the same as that of winapi. Press the Q key, the mouse will move to the A coordinate, press the W key to move to the B coordinate, and press the E key to move to the C coordinate.

2

Then we can calculate the coordinate of D based on the distance between A and D, which can help you solve the problem of moving two adjacent coordinates.

Sample Image

In addition, we can fine-tune the distance according to the actual situation.

Add the following code,

mouseAction(267-87, 337-65, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE); // D(267-87, 337-65)

Sample Image



Related Topics



Leave a reply



Submit