2013-09-03 3 views
3

로봇을 사용하여 몇 초마다 특정 키를 누르는 프로그램을 Java에서 만들려고합니다. GUI에는 시작 및 중지 버튼이 있고 어떤 상태인지 알 수있는 레이블이 있습니다. "시작"을 클릭하면 로봇 기능 (무한대)을위한 루프가 실행됩니다. 생각했던 것처럼 멈춤 버튼을 사용할 수 없습니다. 나는 무한 루프가 놓여있는 곳에서 무언가 어리 석다는 것을 안다.하지만 올바르게 작동하게 만드는 방법을 모르겠다.JButton에서 함수 실행

나는 많은 자바 작업을하지 않지만, 이것은 시도해 보려고 생각한 재미있는 부분 이었지만 부분적으로 멈추었다. 어떤 도움을 주셔서 감사합니다.

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 메소드는 스윙의 이벤트 파견 스레드에서 호출, 그리고 당신이 무한 루프에 진입하고 있기 때문에, 그것은 GUI를 일으킬 수 있습니다 얼어 버려. 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의 사용합니다. *)를 사용하는 것이 좋습니다. nachokk이 제안한 또 다른 방법은 타이머 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();