0

after the loop is finished all buttons and textfields are useable, but while the loop is running nothing can be clicked. i have tried lots of different things, looked on lots of different sites but nothing can help me. i cant find out what is wrong!

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

 public class J extends JFrame implements ActionListener{    
    JButton start = new JButton("Start (F12)");
    JButton stop = new JButton("Stop");

    int i;
    JLabel delay = new JLabel("Delay: ");
    JTextField delayJTF = new JTextField(4);
    int delayS = 0;
    GridLayout bl = new GridLayout(10, 10);
    public J() 
    {      

    super("Auto Clicker");
    start.addActionListener(this);
    stop.addActionListener(this);
    setSize(300, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(bl);
    add(delay, BorderLayout.NORTH);
    add(delayJTF, BorderLayout.NORTH);
    add(start);
    add(stop);
    setVisible(true);




     }

      boolean run = false;



          public static void main(String[] args) {
         J j = new J();

       }
        public void robott() {
         try {

      Robot robot = new Robot();

       Thread.sleep(delayS);
    robot.mousePress(InputEvent.BUTTON1_MASK);    
     robot.mouseRelease(InputEvent.BUTTON1_MASK);
   // robot.delay(delayS);

   } catch(Exception exc) {
      System.out.println(exc);

  }
      }

    public void actionPerformed(ActionEvent e) {
    String delaySt = delayJTF.getText();
    delayS = Integer.parseInt(delaySt);
    System.out.println(delayS);

    while(i < 100) {
        i++;          
      robott();
      System.out.println(i);
    }


   }

 }


     any suggestions?
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
JAVA
  • 29
  • 5
  • 3
    Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling `Thread.sleep(n)` implement a Swing `Timer` for repeating tasks or a `SwingWorker` for long running tasks. See [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) for more details. – Andrew Thompson Jul 24 '12 at 05:09
  • possible duplicate of [Why is my JTextArea not updating?](http://stackoverflow.com/questions/6774414/why-is-my-jtextarea-not-updating) – Andrew Thompson Jul 24 '12 at 05:12

5 Answers5

7

You are looping in the Event Dispatch Thread - the thread that handles GUI painting and user input. All action events are handled on that thread. if you need to perform long running tasks (and other blocking operations like I/O), you should look into off-loading those tasks to a worker thread. Take a look at this tutorial for more info.

akf
  • 38,619
  • 8
  • 86
  • 96
1

I have modified your code now it is working.....You can learn more about worker thread

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

 public class J extends JFrame implements ActionListener{    
JButton start = new JButton("Start (F12)");
JButton stop = new JButton("Stop");

int i;
JLabel delay = new JLabel("Delay: ");
JTextField delayJTF = new JTextField(4);
int delayS = 0;
GridLayout bl = new GridLayout(10, 10);
public J() 
{      

    super("Auto Clicker");
    start.addActionListener(this);
    stop.addActionListener(this);
    setSize(300, 300);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(bl);
    add(delay, BorderLayout.NORTH);
    add(delayJTF, BorderLayout.NORTH);
    add(start);
    add(stop);
    setVisible(true);




}

boolean run = false;



public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            J j=new J();
        }
    });

}
public void robott() {
    try {



        Robot robot = new Robot();
        Thread.sleep(delayS);
        robot.mousePress(InputEvent.BUTTON1_MASK);    
        robot.mouseRelease(InputEvent.BUTTON1_MASK);


    } catch(Exception exc) {
        System.out.println(exc);

    }
}

public void actionPerformed(ActionEvent e) {


             WorkerThread  wt=new WorkerThread();
            wt.execute();

}
class WorkerThread extends SwingWorker<Void , Void>{

    @Override
    protected Void doInBackground() throws Exception {
        String delaySt = delayJTF.getText();
        delayS = Integer.parseInt(delaySt);
        System.out.println(delayS);
        while(i < 100) {

            i++;          
            robott();
            System.out.println(i);
        }
        return null;
    }

}

}

Dangling Piyush
  • 3,658
  • 8
  • 37
  • 52
  • What is the reason for the `invokeLater` call in the `actionPerformed` method ? – Robin Jul 24 '12 at 05:37
  • 2
    Also worth mentioning is that calling the `Robot` methods outside the EDT is not only allowed, but simply needed. See [this question](http://stackoverflow.com/questions/10468432/do-robot-methods-need-to-be-run-on-the-event-queue) for more information – Robin Jul 24 '12 at 05:38
  • Since i am using worker thread so it must be started by another thread – Dangling Piyush Jul 24 '12 at 05:39
  • 1
    *it must be started by another thread* ... the `actionPerformed` method is called on the EDT, and you execute the `WorkerThread` also on the EDT. Where is that other `Thread`. I am arguing you can simply remove that whole `invokeLater` call and just do `new WorkerThread().execute();` in the `actionPerformed` method – Robin Jul 24 '12 at 05:41
  • Yeah you are right i missed that one..i will do the edit...thanks – Dangling Piyush Jul 24 '12 at 05:44
1

As already pointed out, all long-running tasks must execute on a separate thread from the Event Dispatch Loop's thread. On the other hand, all interactions with GUI elements must occur on the Event Dispatch Thread.

In Dangling Piyush's example, the WorkerThread calls robott(), which calls Robot. In this case, the Robot call is "safe".

However if there were to be any direct interaction with Swing GUI elements then those interactions must be re-routed back into the Event Dispatch Loop's Thread.

METHOD A: SwingWorker has publish/process. Override process with code to update GUI. Call publish from your implementation of doInBackground, which "schedules" process to be called from the Event Dispatch Loop (on it's thread). This facilitates moving data across that boundry as parameters.

METHOD B: Call SwingUtilities.invokeLater(Runnable doRun) with a Runnable you define to update GUI elements. That runnable will be run on the desired thread.

Richard Sitze
  • 8,262
  • 3
  • 36
  • 48
1

This is because you run the GUI and loop in one thread .You can set one break point on the method actionPerformed() . It will be found it still is running the while piece which can not accept any other event .

JZH
  • 47
  • 2
0

You should run the while loop in a separate thread. You cant press any button because you are running in the same GUI thread the while loop. Just remember that swing components are not thread safe so use invoke later in all components.

rsan
  • 1,887
  • 2
  • 17
  • 23