2013-09-03 5 views
3

Я пытаюсь сделать программу в java, которая использует робот, чтобы нажимать определенный ключ каждые несколько секунд. Он имеет графический интерфейс с кнопкой запуска и остановки и меткой, в которой указывается, в каком состоянии она находится. У меня есть все, что работает до сих пор, за исключением того, что когда я нажимаю «запускать», он запускает цикл для моей функции робота (что бесконечно) не позволяет кнопку остановки, как я думал, это будет. Я знаю его что-то глупое, где помещается бесконечный цикл, но я не уверен, как заставить его работать правильно.Функция запуска на JButton press

Я не очень много работаю в java, это была просто забавная вещь, которую я решил попробовать, но застрял частично. Любая помощь приветствуется.

import java.awt.AWTException; 
import java.awt.FlowLayout; 
import java.awt.Robot; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 

public class Main extends JFrame { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 
    private static boolean running = false;; 
    private JButton start_button; 
    private JButton stop_button; 
    private JLabel tl; 
    private static int i = 0; 
    Robot robot; 

    void start() { 

     JFrame frame = new JFrame("Helper"); 
     tl = new JLabel("Running: " + running); 
     start_button = new JButton("Start"); 
     stop_button = new JButton("Stop"); 
     stop_button.setEnabled(false); 
     frame.add(tl); 
     frame.add(start_button); 
     frame.add(stop_button); 
     frame.setSize(300, 100); 
     frame.setVisible(true); 
     frame.setLayout(new FlowLayout()); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.setLocation(400, 400); 

     try { 
      robot = new Robot(); 
     } catch (AWTException e2) { 
      // TODO Auto-generated catch block 
      e2.printStackTrace(); 
     } 
     robot.setAutoDelay(200); 

     start_button.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       start_button.setEnabled(false); 
       stop_button.setEnabled(true); 
       running = true; 
       tl.setText("Running: " + running); 
       while (running) { 
        robot_loop(robot); 
       } 

      } 
     }); 
     stop_button.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       start_button.setEnabled(true); 
       stop_button.setEnabled(false); 
       running = false; 
       tl.setText("Running: " + running); 

      } 
     }); 

    } 

    public static void main(String[] args) { 
     new Main().start(); 

    } 

    private static void robot_loop(Robot robot) { 

     robot.keyPress(KeyEvent.VK_NUMPAD0); 
     robot.keyRelease(KeyEvent.VK_NUMPAD0); 

     System.out.println("numpad 0 pressed! - " + i); 
     i++; 

    } 

} 
+2

Метод actionPerformed этих обработчиков событий вызываются по отправке потока событий Свинг, и так как вы вводите в бесконечный цикл, это будет вызывать графический интерфейс пользователя заморозить. Вы можете создать поток внутри вашего метода actionPerformed и выполнить свою работу внутри нового потока. Хотя следующая проблема, с которой вы столкнулись, находит хороший способ остановить поток всякий раз, когда пользователь нажимает кнопку остановки. – sgbj

+1

Используйте swingtimer insteas – nachokk

ответ

6

Я адаптировал свой комментарий в ответ.

ActionPerformed метод этих прослушивателей событий вызывается в потоке отправки событий Swing, и поскольку вы входите в бесконечный цикл, это вызовет зависание GUI. Вы можете создать поток внутри вашего метода actionPerformed и выполнить свою работу внутри нового потока. Хотя следующая проблема, с которой вы столкнулись, находит хороший способ остановить поток всякий раз, когда пользователь нажимает кнопку остановки.

Что круто, так это то, что у вас уже есть логика для этого в коде. Так заставить его работать так же просто, как изменение:

start_button.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      start_button.setEnabled(false); 
      stop_button.setEnabled(true); 
      running = true; 
      tl.setText("Running: " + running); 
      while (running) { 
       robot_loop(robot); 
      } 

     } 
    }); 

Чтобы сделать вашу работу по своей теме:

start_button.addActionListener(new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      start_button.setEnabled(false); 
      stop_button.setEnabled(true); 
      running = true; 
      tl.setText("Running: " + running); 
      Executors.newSingleThreadExecutor().submit(new Runnable() { 
       @Override public void run() { 
        while (running) { 
         robot_loop(robot); 
        } 
       } 
      }); 
     } 
    }); 

Код выше использует рамки исполнителей (java.util.concurrent. *) вместо прямого создания потока. Другой альтернативой, предлагаемой начокком, было бы использовать таймер java.util.Timer или javax.swing.Timer (либо в этом случае должно быть хорошо).

+0

Это прекрасно! спасибо за помощь! Единственное разочарование, которое у меня нет, это одно дополнительное прессу после того, как вы нажмете стоп, но это действительно не имеет большого значения. Спасибо за помощь! – Kynian

1

Вы можете сделать что-то вроде этого, используя SwingTimer

 int delay = 400*1000;// you can inject this property 
     ActionListener taskPerformer = new ActionListener(){ 
       @Override 
       public void actionPerformed(ActionEvent evt2) { 
       robot_loop(robot); 
       } 

     }; 

      Timer timer = new Timer(delay, taskPerformer); 
      timer.start(); 
Смежные вопросы