JAVA Robot mouseMove 2 Monitors - java

I'm trying to write a program that would bring the mouse cursor to certain coordinates, according to timings, regardless of the user. I wrote a simple code using Robot, but ran into a problem ... I have two monitors, and the cursor moves incorrectly depending on what monitor it is on at the moment, please tell me how to solve the problem.
The code below is what I was trying to create ...
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] graphicsDevices = graphicsEnvironment.getScreenDevices();
for(int i=0; i < graphicsDevices.length; i++)
{
System.out.println(graphicsDevices[i]);
}
try {
//Robot robot = new Robot(MouseInfo.getPointerInfo().getDevice());
Robot robot = new Robot();
while(true)
{
robot.mouseMove(-1640, -3);
robot.mousePress(InputEvent.BUTTON1_MASK);
robot.mouseRelease(InputEvent.BUTTON1_MASK);
Thread.sleep(10000);
}
} catch (Exception e) {
e.printStackTrace();
}

You should work with the idea of get the resolution and then move from there. You are doing ABSOLUTE moves and they will work different in differents setups.
You should use this code
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
int width = gd.getDisplayMode().getWidth();
int height = gd.getDisplayMode().getHeight();
from there you could:
Robot robot = new Robot();
robot.mouseMove (width-10, height+3);
So you would move relatively to the specs of the monitor. I hope I have helped.

Related

Cropping BufferedImage For Use in Xuggle encodeVideo

I have an application to capture video of the screen and save to a file. I give the user the ability to pick between 480, 720, and "Full Screen" video sizes. A 480 will record in a small box on the screen, 720 will record in a larger box, and of course, "Full Screen" will record in an even larger box. However, this full screen box is NOT the actual screen resolution. It is the app window size, which happens to be around 1700x800. The Video Tool works perfectly for the 480 and 720 options, and will also work if "Full Screen" is overwridden to be the entire screen of 1920x1080.
My question: Are only certain sizes allowed? Does it have to fit a certain aspect ratio, or be an "acceptable" resolution? My code, below, is modified from the xuggle CaptureScreenToFile.java file (the location of the problem is noted by comments):
public void run() {
try {
String parent = "Videos";
String outFile = parent + "example" + ".mp4";
file = new File(outFile);
// This is the robot for taking a snapshot of the screen. It's part of Java AWT
final Robot robot = new Robot();
final Rectangle customResolution = where; //defined resolution (custom record size - in this case, 1696x813)
final Toolkit toolkit = Toolkit.getDefaultToolkit();
final Rectangle fullResolution = new Rectangle(toolkit.getScreenSize()); //full resolution (1920x1080)
// First, let's make a IMediaWriter to write the file.
final IMediaWriter writer = ToolFactory.makeWriter(outFile);
writer.setForceInterleave(false);
// We tell it we're going to add one video stream, with id 0,
// at position 0, and that it will have a fixed frame rate of
// FRAME_RATE.
writer.addVideoStream(0, 0, FRAME_RATE, customResolution.width, customResolution.height); //if I use fullResolution, it works just fine - but captures more of the screen than I want.
// Now, we're going to loop
long startTime = System.nanoTime();
while (recording) {
// take the screen shot
BufferedImage screen = robot.createScreenCapture(fullResolution); //tried capturing using customResolution, but did not work. Instead, this captures full screen, then tries to trim it below (also does not work).
// convert to the right image type
BufferedImage bgrScreen = convertToType(screen, BufferedImage.TYPE_3BYTE_BGR); //Do I need to convert after trimming?
BufferedImage trimmedScreen = bgrScreen.getSubimage((int)customResolution.getX(), (int)customResolution.getY(), (int)customResolution.getWidth(), (int)customResolution.getHeight());
// encode the image
try{
//~~~~Problem is this line of code!~~~~ Error noted below.
writer.encodeVideo(0, trimmedScreen, System.nanoTime() - startTime, TimeUnit.NANOSECONDS); //tried using trimmedScreen and bgrScreen
} catch (Exception e) {
e.printStackTrace();
}
// sleep for framerate milliseconds
Thread.sleep((long) (1000 / FRAME_RATE.getDouble()));
}
// Finally we tell the writer to close and write the trailer if
// needed
writer.close();
} catch (Throwable e) {
System.err.println("an error occurred: " + e.getMessage());
}
}
public static BufferedImage convertToType(BufferedImage sourceImage, int targetType) {
BufferedImage image;
// if the source image is already the target type, return the source image
if (sourceImage.getType() == targetType)
image = sourceImage;
// otherwise create a new image of the target type and draw the new image
else {
image = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), targetType);
image.getGraphics().drawImage(sourceImage, 0, 0, null);
}
return image;
}
Error:
java.lang.RuntimeException: could not open stream com.xuggle.xuggler.IStream#2834912[index:0;id:0;streamcoder:com.xuggle.xuggler.IStreamCoder#2992432[codec=com.xuggle.xuggler.ICodec#2930320[type=CODEC_TYPE_VIDEO;id=CODEC_ID_H264;name=libx264;];time base=1/50;frame rate=0/0;pixel type=YUV420P;width=1696;height=813;];framerate:0/0;timebase:1/90000;direction:OUTBOUND;]: Operation not permitted
Note: The file is successfully created, but has size of zero, and cannot be opened by Windows Media Player, with the following error text:
Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file.
Sorry for the wordy question. I'm interested in learning WHAT and WHY, not just a solution. So if anyone can explain why it isn't working, or point me towards material to help, I'd appreciate it. Thanks!
Try to have the dimension even numbers 1696x812

Selenium WebDriver and Java Robot Class

I want to use the Java Robot class in order to move the mouse over a link to dynamically create more content. For the web interactions I use the Selenium WebDriver.
Point coordinates = driver.findElement(By.xpath("//li[#id='1234']/a")).getLocation();
Robot robot;
try {
robot = new Robot();
robot.mouseMove(coordinates.getX(),coordinates.getY()+120);
} catch (AWTException e1) {
e1.printStackTrace();
}
Selenium throws an error for the getLocation function:
Exception in thread "main" org.openqa.selenium.WebDriverException: Cannot determine size of element
Does anybody know what am I doing wrong?
mouseover action you can achieve (Actions class) without using Robot also.
new Actions(driver).moveToElement(driver.findElement(By.xpath("//li[#id='1234']/a"))).perform();
include below import statement in your file.
import org.openqa.selenium.interactions.Actions;
If you just want to make a mouse movement on the page, Selenium interactions can help you do the same.
Here is the sample code for you
WebElement myLink = driver.findElement(By.xpath("//li[#id='1234']/a"));
Actions act = new Actions(driver);
act.moveToElement(myLink).build().perform();
// if you want to click on the link :
act.click(myLink).build().perform();
// if you want to move to the element and then click onthe link :
act.moveToElement(myLink).click(myLink).build().perform();
// or can be done in two different steps like this :
act = act.moveToElement(myLink);
act.click(myLink).build().perform()
For doing this we should import org.openqa.selenium.interactions.Actions;
Hope this solves your problem.
I tried this and it seems to work for me. Please check
Point p = webele.getLocation();
int x = p.getX();
int y = p.getY();
Dimension d = webele.getSize();
int h = d.getHeight();
int w = d.getWidth();
Robot r = new Robot();
r.mouseMove(x + (w/2), y+(h/2) +80);

JLabel Icon not showing after change

I tried looking up this question, but most of the answers are that the file path is wrong, but that's most likely not the case. The file works the 1st time I use it.
I am making a battleships game, and use JLabels to show ships on map. I want to make a button to rotate ship from horizontal to vertical but it's icon disappears when I try to change it.
When I run this constructor code:
public Ship(int size, String direction, boolean active, Client c,
ClientGUI cg) {
this.c = c;
this.cg = cg;
health = size;
this.active = active;
this.direction = direction;
file = "img/" + Integer.toString(health) + direction + ".png"; // String
try {
System.out.println(file);
tx = ImageIO.read(new File(file)); // BufferedImage
} catch (IOException e) {
e.printStackTrace();
}
texture = new JLabel(new ImageIcon(tx));
if (direction.equals("v"))
texture.setBounds(0, 0, 40, 40 * size);
else
texture.setBounds(0, 0, 40 * size, 40);
texture.setVisible(true);
}
everything works and I can see the image.
But then I try to rotate it, using pretty much the same code:
void rotate() {
if (direction.equals("h")) {
direction = "v";
file = "img/" + Integer.toString(health) + direction + ".png";
try {
System.out.println(file);
tx = ImageIO.read(new File(file));
} catch (IOException e) {
e.printStackTrace();
}
texture.setBounds(0,0,40, 40 * size);
texture.setIcon(new ImageIcon(tx));
} else {
direction = "h";
file = "img/" + Integer.toString(health) + direction + ".png";
try {
System.out.println(file);
tx = ImageIO.read(new File(file));
} catch (IOException e) {
e.printStackTrace();
}
texture.setIcon(new ImageIcon(tx));
texture.setBounds(0,0,40 * size, 40);
}
cg.repaint(); // not sure if I need to do this
}
and it disappears...
I tried placing two ships, one is rotated, it's just missing the JLabel or the icon on JLabel.
If you update the JLabel texture by calling a method which changes it's state, it may or may not be updated immediately unless you call texture.repaint() or texture.paintAll(texture.getGraphics()), or some similar method.
Also, I would look into using a LayoutManager for whatever upper level component you are using to hold your grid of JLabels. If you use a GridLayout of your game board and either:
set the JLabel's preferred size with texture.setPreferredSize(Dimension) and call frame.pack() once when setting up your game; or
set the JLabel's size with label.setSize(Dimension) once and don't pack your JFrame
You will only need to set the size of the JLabel once, not every time you set a new ImageIcon to the label. Because, Ideally your game shouldn't be doing any extra work that it doesn't have to so it performs faster.
I would also recommend maintaining every possible ImageIcon as static fields in your class, rather than accessing them from the file every time. That way, you read them once from a static initializing method, which then reach ship can directly access when changing the direction.
I want to make a button to rotate ship from horizontal to vertical
You can use the Rotated Icon class to do the rotation for you.

How to control (move) the mouse cursor?

How do I move the mouse cursor (windows) with Java?
I have a pair of values constantly being updated. I want to use them to control the cursor.
Robot.mouseMove(x,y)
As mentioned in:
https://stackoverflow.com/a/2941373/1150918 by OscarRyz.
You will need to use the Robot class.
Robot r = null;
try {
r = new Robot();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
r.mouseMove(x, y);//x is the horizontal position on the screen, y is the vertical

Recognize in which monitor the application runs in Java

I'm writing an Snipping Tool application. I have connected another moniter to my laptop. Application must recognize which monitor it currently is running on and capture it's screen. Like when I run the application in the external monitor I need to capture the screen of it.
Code I used to do this needed to be provide the monitor number. But I want the application to recognize it.
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
gs[0].getDisplayMode();
Dimension mySize = new Dimension(width, height);
width = (int) mySize.getWidth();
height = (int) mySize.getHeight();
You can do this:
JFrame frame = new JFrame();
// ...
GraphicsDevice device = frame.getGraphicsConfiguration().getDevice();

Categories