3

ロボットを使用して特定のキーを数秒ごとに押すプログラムを Java で作成しようとしています。開始および停止ボタンと、どの状態にあるかを示すラベルを備えた GUI があります。「開始」をクリックすると、ロボット機能のループが実行されることを除いて (これは無限です)、これまでのところすべてが機能しています。思ったように停止ボタンが有効になりません。無限ループが配置されている場所がおかしいことは知っていますが、それを正しく機能させる方法がわかりません。

私は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++;

    }

}
4

2 に答える 2

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

上記のコードは、スレッドを直接作成するのではなく、executors フレームワーク (java.util.concurrent.*) を利用しています。nachokk が提案した別の方法は、タイマーjava.util.Timerまたはjavax.swing.Timer(この場合はどちらでも問題ありません) を使用することです。

于 2013-09-03T03:15:27.013 に答える
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();
于 2013-09-03T03:24:02.607 に答える