Sto utilizzando java.awt.Robot
per i test di integrazione della mia applicazione Swing, ma ho problemi a eseguire le mie azioni nell'ordine corretto. Come posso dire al thread che chiama robot.mousePressed(...)
di bloccare fino a quando Swing ha finito di inviare quell'evento? Apparentemente, robot.setAutoWaitForIdle(true)
non va bene.java.awt.Robot.waitForIdle() attende la spedizione degli eventi?
Ecco la mia demo. Mi aspetto che il "robot finisca!" messaggio che viene sempre dopo "Azione terminata il blocco", ma invece spesso accade troppo presto.
import java.awt.AWTException;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.sql.Date;
import java.text.DateFormat;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class RobotWaitForIdleDemo {
/**
* Create the device that contains the given point in screen coordinates.
* Robot has to be constructed differently for each monitor.
*/
public static GraphicsDevice getDevice(Point p) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
// Search the devices for the one that draws the specified point.
for (GraphicsDevice device : gs) {
GraphicsConfiguration configuration = device.getDefaultConfiguration();
Rectangle bounds = configuration.getBounds();
if (bounds.contains(p)) {
return device;
}
}
return null;
}
public static final Logger logger = Logger.getLogger(RobotWaitForIdleDemo.class.getName());
public static void main(String[] args) {
LogManager.getLogManager().reset();
Formatter formatter = new Formatter() {
@Override
public String format(LogRecord arg0) {
Date date = new Date(arg0.getMillis());
DateFormat.getTimeInstance().format(date);
return String.format("%s %s %s %s%n",
DateFormat.getTimeInstance().format(date),
arg0.getLoggerName(),
arg0.getLevel(),
arg0.getMessage());
}
};
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setFormatter(formatter);
logger.addHandler(consoleHandler);
final JFrame jframe = new JFrame("Robot experiment");
GroupLayout groupLayout = new GroupLayout(jframe.getContentPane());
final JButton jbutton = new JButton("Click me!");
jbutton.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
// Simulate a heavy Swing event handler.
logger.info("(swing thread) Action starting to block...");
try {
Thread.sleep(500);
} catch (InterruptedException e1) {}
logger.info("(swing thread) Action finished blocking.");
}
});
JButton tryAgainBUtton = new JButton("Automatically click above button.");
tryAgainBUtton.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
new Thread(new Runnable() {
@Override public void run() {
try {
Point point = new Point(jbutton.getWidth()/2,jbutton.getHeight()/2);
SwingUtilities.convertPointToScreen(point, jbutton);
GraphicsDevice device = getDevice(point);
Point offset = device.getDefaultConfiguration().getBounds().getLocation();
Robot robot = new Robot(device);
robot.setAutoWaitForIdle(true);
robot.setAutoDelay(30);
robot.mouseMove(point.x - offset.x, point.y - offset.y);
String threadName = Thread.currentThread().getName();
logger.info(String.format("(%s) robot.mousePress(%d)", threadName, InputEvent.BUTTON1_MASK));
robot.mousePress(InputEvent.BUTTON1_MASK);
logger.info(String.format("(%s) robot.mouseRelease(%d)", threadName, InputEvent.BUTTON1_MASK));
robot.mouseRelease(InputEvent.BUTTON1_MASK);
logger.info(String.format("(%s) robot finished!", threadName, InputEvent.BUTTON1_MASK));
} catch (AWTException ex) {
ex.printStackTrace();
}
}
}, "robot thread").start();
}
});
jframe.getContentPane().setLayout(groupLayout);
groupLayout.setAutoCreateGaps(true);
groupLayout.setAutoCreateContainerGaps(true);
groupLayout.setVerticalGroup(
groupLayout.createSequentialGroup()
.addComponent(jbutton)
.addComponent(tryAgainBUtton));
groupLayout.setHorizontalGroup(
groupLayout.createParallelGroup()
.addComponent(jbutton)
.addComponent(tryAgainBUtton) );
jframe.setSize(300, 300);
jframe.setVisible(true);
jframe.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
}
}
Sto eseguendo Java 1.6 su Ubuntu.
+1 per [sscce] (http://sscce.org/); vedere anche [Thread iniziali] (http://download.oracle.com/javase/tutorial/uiswing/concurrency/initial.html). – trashgod