I've been trying to create an autoclicker in java using jnativehook.
It works fine, even compiles and runs. My problem is using Thread.sleep to try and add a delay between clicks:
bot.mousePress(InputEvent.BUTTON1_MASK);
Thread.sleep(50);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
If I were to input a delay of 0 it will function fine. But given no delay it will click too fast.
When I add a delay it will click fine but, when I release the trigger key it will keep clicking for a few seconds given the time it's been clicking. A delay of 0 will not do this however.
Full code:
public class App implements NativeKeyListener{
private JPanel panel1;
private JTabbedPane tabbedPane1;
private JButton spoilerButton;
private JSlider slider1;
private JSlider slider2;
//Removed irrelevant code...
static Robot bot;
static {
try {
bot = new Robot();
} catch (Exception e) {
e.printStackTrace();
}
}
static boolean pressed;
public void click() throws InterruptedException {
try {
bot.mousePress(InputEvent.BUTTON1_MASK);
Thread.sleep(50);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (Exception e) {
e.printStackTrace();
}}
#Override
public void nativeKeyPressed(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode()) == "Delete") {
pressed = true;
while (pressed){
try {
click();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}}
#Override
public void nativeKeyReleased(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode())=="Delete"){
pressed=false;
}}
#Override
public void nativeKeyTyped(NativeKeyEvent e) {
}
public static void main(String[] args) {
JFrame frame = new JFrame("Autoclicker");
frame.setContentPane(new App().panel1);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setSize(400,148);
frame.setResizable(false);
try{GlobalScreen.registerNativeHook();
} catch (Exception e){
System.exit(1);}
GlobalScreen.addNativeKeyListener(new App());
}
}
Looks like the method nativeKeyPressed() gets called continuously when you keep pressing the trigger key. This results in several calls to click() method (assuming it's multi threaded) and due to the sleep() between mouse press and release (mouse click is complete when released) this can happen.
Hence you can try two options depending on the root cause:
1. move the sleep() call after mouse released. If the nativeKeyPressed gets called concurrently this won't work.
2. Use a different thread to execute the click() method when trigger is pressed. In this case, you may need to submit a Runnable object to your thread each time with the 'pressed' check and click() call in it. This will ensure it won't run after pressed becomes false.
Related
When I call the JFrame from another class to test, the JFrame works, but when I insert it into my Selenium test, the JFrame and the browser open so quickly that there's no time to input anything and the test appears like passed.
Sample of the elements that I mention:
#Test
public void Run() throws InterruptedException{
Keys.loginFrame(); //This method is static in another class named 'Keys'
...
}
Is there any way to say to Selenium the following?:
Execute first ONLY Keys.loginFrame();, then wait till the JFrame is closed. Finally execute the rest of the test code.
Thank you for your answers!
remake your loginFrame() method to return JFrame object
add this method:
public static void startFrameThread(JFrame frame) {
Thread thread = new Thread() {
public void run() {
while (frame.isVisible()) {
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
}
}
}
};
thread.start();
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent arg0) {
frame.setVisible(false);
}
});
try {
thread.join();
} catch (InterruptedException e) {
}
}
apply new usage:
JFrame loginFrame = Keys.loginFrame();
loginFrame.setVisible(true); // if not setting visible in loginFrame() method
startFrameThread(loginFrame);
private void runInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
while (running) {
try {
checkPixel();
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void stop() {
this.running = false;
}
public void start() {
this.running = true;
}
So I have some code someone provided me to monitor the change in color in the middle of the screen. I want to essentially turn on/off checkPixel() after I press something like F9 but how can I do this without a GUI because I can't seem to find anything that allows this. I believe KeyListeners only work with GUIs?
EDIT: Ok so instead while I'm checking for pixel changes in the thread. Once a pixel change has been detected I want to cause create a "left click action" in checkPixel() then turn off the thread. Any help with this?
I guess you want functionality provided by JNativeHook library.
The library allows for grabbing a key from the backgrond.
Can't figure this one out. Using worker or invokeLater, the UI still freeze. After each file is downloaded, I want a JList to be updated. But the JList will only update after the tread returns.
Here is the code:
public class MyUi extends javax.swing.JFrame{
...
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt){
SwingUtilities.invokeLater(new Runnable() {
//To get out of the event tread
public void run() {
dl();
}
});
}
private void dl(){
...
//ini and run the download class
Download myDownload = new Download();
myDownload.doDownload(myDlList);
}
public void updateJlist(String myString){
myModel.addElement(myString);
jList1.repaint();
}
}
public class Download{
...
public void doDownload(String[] fileName){
for(int i=0; i<fileName.length; i++){
...//download action...
//for my jList1 to be updated after each file.
MyUi.updateJlist(fileName[i]);
}
}
}
Any example would help.
invokeLater does exactly the opposite of what you expect it to do - it runs operations on the EDT, which explains the behaviour.
Download the file on a background thread and wrap just updateJlist() in a Runnable.
SwingWorker would be more reliable.
Addendum: As #mre notes, SwingWorker also makes it easy to report interim results, as shown here.
I have create a WorkerThread class which take care of Threads and GUI current/main thread . i have put my GUI application in construct() method of WorkerThread when an event fire to start XXXServer then all threads are activate and GUI work smoothlly wihout freeze. have a look.
/** * Action Event * * #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */
public void actionPerformed(ActionEvent ae) {
log.info("actionPerformed begin..." + ae.getActionCommand());
try {
if (ae.getActionCommand().equals(btnStart.getText())) {
final int portNumber = 9990;
try {
WorkerThread workerThread = new WorkerThread(){
public Object construct(){
log.info("Initializing the Server GUI...");
// initializing the Server
try {
xxxServer = new XXXServer(portNumber);
xxxServer.start();
btnStart.setEnabled(false);
} catch (IOException e) {
// TODO Auto-generated catch block
log.info("actionPerformed() Start button ERROR IOEXCEPTION..." + e.getMessage());
e.printStackTrace();
}
return null;
}
};workerThread.start();
} catch (Exception e) {
log.info("actionPerformed() Start button ERROR..." + e.getMessage());
e.printStackTrace();
}
} else if (ae.getActionCommand().equals(btnStop.getText())) {
log.info("Exit..." + btnStop.getText());
closeWindow();
}
} catch (Exception e) {
log
.info("Error in ServerGUI actionPerformed==="
+ e.getMessage());
}
}
I have a jbutton which I want, as soon as it's clicked to make an infinite loop of a mouseMove by a robot class. Then, to be stopped when it is clicked again. Problem is in my code when I press it for the first time, it causes the system to freeze and nothing happens when I click it again. I use:
boolean go = false
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
go = !go;
if (go)
jb.setText("Stop!");
else
jb.setText("Start!");
try {
Robot robot = new Robot();
while (go) {
robot.mouseMove(500, 500);
robot.delay(1000);
robot.mouseMove(500, 400);
}
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
Swing is a single threaded environment. This means that if anything should block this thread, Swing will be unable to respond to new events, including paint requests and it will appear that you UI has been frozen...because it has...
Take a look at Concurrency in Swing
The simplest solution might be to spawn a new thread and run your loop within it...
Start by writing a Runnable that handels the work you want done...
public class MouseRunner implements Runnable {
#Override
public void run() {
try {
Robot robot = new Robot();
while (go) {
robot.mouseMove(500, 500);
robot.delay(1000);
robot.mouseMove(500, 400);
}
} catch (AWTException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
Then when the user first clicks the button, create a Thread and start it...
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
go = !go;
if (go) {
jb.setText("Stop!");
Thread t = new Thread(new MouseRunner());
t.start();
} else {
jb.setText("Start!");
}
}
});
Beware, your go variable is likely going to need to made volatile
In my application, in a JDesktopPane I have added few JInternalFrames. Activation and deactivation of JInternalFrames happen normally, until one of the JInternalFrame is maximized. After that, activating an internalframe programmatically, fires internalFrameActivated, internalFrameDeactivated events multiple times. Why it is called many times? This I have observed in WindowsLookAndFeel only
public class IFTest {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(new WindowsLookAndFeel());
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
JFrame frame = new JFrame();
JDesktopPane pane = new JDesktopPane();
JInternalFrame if1 = new JInternalFrame("IF1");
JInternalFrame if2 = new JInternalFrame("IF2");
if1.setTitle("IF1");
if2.setTitle("IF2");
pane.add(if1);
pane.add(if2);
frame.getContentPane().add(pane);
frame.setSize(500, 500);
frame.setVisible(true);
if1.setMaximizable(true);
if1.setSize(400, 400);
showInternalFrame(if1);
if1.addInternalFrameListener(new MyInternalFrameListener("IF1"));
if2.setMaximizable(true);
if2.setSize(300, 300);
if2.setVisible(true);
showInternalFrame(if2);
if2.addInternalFrameListener(new MyInternalFrameListener("IF2"));
System.out.println("------------------------------");
try {
if1.setMaximum(true);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
System.out.println("--------------------------------");
showInternalFrame(if2);
}
static class MyInternalFrameListener extends InternalFrameAdapter {
String name;
public MyInternalFrameListener(String name) {
this.name = name;
}
#Override
public void internalFrameActivated(InternalFrameEvent e) {
System.out.println(name + " activated");
}
#Override
public void internalFrameIconified(InternalFrameEvent e) {
System.out.println(name + " iconfied");
}
#Override
public void internalFrameDeactivated(InternalFrameEvent e) {
System.out.println(name + " deactivated");
}
#Override
public void internalFrameDeiconified(InternalFrameEvent e) {
System.out.println(name + " deiconfied");
}
}
public static void showInternalFrame(JInternalFrame intf) {
try {
if (intf.isIcon())
intf.setIcon(false);
intf.setVisible(true);
intf.moveToFront();
intf.setSelected(true);
} catch (PropertyVetoException ex) {
ex.printStackTrace();
}
}
}
Why it is called many times?
I would guess that it doesn't like to have multiple frames maximized at one time. In a normal GUI you would have to restore the currently maximized frame before you could click on another frame to maximizing it.
Your code is:
if1.setMaximum(true);
showInternalFrame(if2);
I noticed that after executing this code, if2 is maximized even though you did not explicitly ask for it to be maximized. So I'm guessing that somewhere in the code to select a frame it realizes that the current frame is maximized so there is a bunch of code that is executing that restores/deactivates the frames a couple of time until if1 is restored and if2 is selected and maximized. The code is obviously generating a bunch of events as it does this.
On the other hand if you have code like:
if1.setMaximum(true);
if1.setMaximum(false);
showInternalFrame(if2);
then you get the events as expected.
So maybe as a solution to your problem you can add code like the following in your showInternalFrame() method:
JinternalFrame active = intf.getDesktopPane().getSelectedFrame();
if (active.isMaximized())
active.setMaximum(false);
ints.setSelected(true);