может ли кто-нибудь помочь мне с тем, почему мой графический интерфейс не активен во время выполнения цикла?

после завершения цикла все кнопки и текстовые поля доступны для использования, но во время выполнения цикла ничего нельзя нажимать. Я пробовал много разных вещей, смотрел на разных сайтах, но ничего не может мне помочь. не могу понять что не так!

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?

person JAVA    schedule 24.07.2012    source источник
comment
Не блокируйте EDT (поток отправки событий) — когда это произойдет, графический интерфейс «зависнет». Вместо вызова Thread.sleep(n) реализуйте Swing Timer для повторяющихся задач или SwingWorker для длительных задач. Дополнительные сведения см. в разделе Параллелизм в Swing.   -  person Andrew Thompson    schedule 24.07.2012
comment
возможный дубликат Почему мой JTextArea не обновляется?   -  person Andrew Thompson    schedule 24.07.2012


Ответы (5)


Вы зацикливаетесь в потоке отправки событий — потоке, который обрабатывает рисование графического интерфейса и пользовательский ввод. Все события действий обрабатываются в этом потоке. если вам нужно выполнять длительные задачи (и другие блокирующие операции, такие как ввод-вывод), вам следует рассмотреть возможность выгрузки этих задач в рабочий поток. Дополнительные сведения см. в этом руководстве.

person akf    schedule 24.07.2012

Я изменил ваш код, теперь он работает..... Вы можете узнать больше о рабочем потоке

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;
    }

}

}

person Dangling Piyush    schedule 24.07.2012
comment
В чем причина вызова invokeLater в методе actionPerformed? - person Robin; 24.07.2012
comment
Также стоит упомянуть, что вызов методов Robot вне EDT не только разрешен, но и просто необходим. См. этот вопрос для получения дополнительной информации. - person Robin; 24.07.2012
comment
Поскольку я использую рабочий поток, он должен быть запущен другим потоком. - person Dangling Piyush; 24.07.2012
comment
он должен быть запущен другим потоком... метод actionPerformed вызывается в EDT, и вы также выполняете WorkerThread в EDT. Где тот другой Thread. Я утверждаю, что вы можете просто удалить весь этот вызов invokeLater и просто выполнить new WorkerThread().execute(); в методе actionPerformed. - person Robin; 24.07.2012
comment
Да, вы правы, я пропустил это ... я отредактирую ... спасибо - person Dangling Piyush; 24.07.2012

Как уже отмечалось, все длительные задачи должны выполняться в потоке, отдельном от потока цикла диспетчеризации событий. С другой стороны, все взаимодействия с элементами GUI должны происходить в потоке отправки событий.

В примере Dangling Piyush WorkerThread вызывает robott(), который вызывает Robot. В этом случае вызов робота «безопасен».

Однако, если должно быть какое-либо прямое взаимодействие с элементами графического интерфейса пользователя Swing, то эти взаимодействия должны быть перенаправлены обратно в поток цикла диспетчеризации событий.

МЕТОД A: SwingWorker имеет publish/process. Переопределите process кодом для обновления графического интерфейса. Вызовите publish из вашей реализации doInBackground, которая "планирует" process для вызова из цикла диспетчеризации событий (в его потоке). Это облегчает перемещение данных через эту границу в качестве параметров.

СПОСОБ B: вызовите SwingUtilities.invokeLater(Runnable doRun) с Runnable, который вы определили для обновления элементов графического интерфейса. Этот исполняемый файл будет запущен в нужном потоке.

person Richard Sitze    schedule 24.07.2012

Это связано с тем, что вы запускаете графический интерфейс и выполняете цикл в одном потоке. Вы можете установить одну точку останова в методе actionPerformed() . Будет обнаружено, что он все еще работает с частью while, которая не может принимать никакие другие события.

person user1461926    schedule 24.07.2012

Вы должны запустить цикл while в отдельном потоке. Вы не можете нажать ни одну кнопку, потому что вы работаете в том же потоке графического интерфейса, что и цикл while. Просто помните, что компоненты Swing не являются потокобезопасными, поэтому используйте вызов вызова позже во всех компонентах.

person Community    schedule 24.07.2012