-1

私は多くのことを試しましたが、何もうまくいかないようです。エスケープを押したときにこのプログラムを終了させるのを手伝ってくれる人はいますか? 私はスレッドの経験があまりないので、それが私の欠点の 1 つかもしれません。

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Font;
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;
import javax.swing.JPanel;


public class Main implements ActionListener {

    public static boolean start = false;

    public static void Start() {

        final JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        JLabel label = new JLabel("Choose Action:");
        JLabel label2 = new JLabel("Hello");
            JButton button1 = new JButton("Start");

        button1.addActionListener(new ActionListener() { 
              public void actionPerformed(ActionEvent e) {

                Robot robot = null;
                try {
                    robot = new Robot();
                } catch (AWTException e1) {
                    e1.printStackTrace();
                }

                start = true;
                System.out.println("Pressed");

                    while(start) {

                           robot.keyPress(KeyEvent.VK_W);
                           try{
                            Thread.sleep(1);
                        } 
                        catch(Exception ex) {

                        }
                        robot.keyRelease(KeyEvent.VK_W);
                        try{
                            Thread.sleep(150);
                        } 
                        catch(Exception ex) {

                        }

                        robot.keyPress(KeyEvent.VK_S);
                        try{
                            Thread.sleep(1);
                        } 
                        catch(Exception ex) {

                        }
                        robot.keyRelease(KeyEvent.VK_S);
                        try{
                            Thread.sleep(150);
                        } 
                        catch(Exception ex) {

                        }

                        robot.keyPress(KeyEvent.VK_A);
                        try{
                            Thread.sleep(1);
                        } 
                        catch(Exception ex) {

                        }
                        robot.keyRelease(KeyEvent.VK_A);
                        try{
                            Thread.sleep(150);
                        } 
                        catch(Exception ex) {

                        }

                        robot.keyPress(KeyEvent.VK_D);
                        try{
                            Thread.sleep(1);
                        } 
                        catch(Exception ex) {

                        }
                        robot.keyRelease(KeyEvent.VK_D);
                        try{
                            Thread.sleep(150);
                        } 
                        catch(Exception ex) {
                    }
                }
              } 
            } );

        JButton button2 = new JButton("Exit");

        button2.addActionListener(new ActionListener() { 
              public void actionPerformed(ActionEvent e) { 
                  start = false;
                frame.dispose();
                System.exit(0);
              } 
            } );

        frame.setTitle("Test");
        frame.setSize(350, 100);
        frame.setResizable(false );
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add(panel);
        panel.add(label);
        panel.add(button1);
        panel.add(button2);
        panel.add(label2, BorderLayout.SOUTH);

    }

    public static void main (String args[]) throws InterruptedException {
        Start();
    }


    @Override
    public void actionPerformed(ActionEvent arg0) {

    }
}

私は正直ここで途方に暮れています。どんな助けでも事前に感謝します。

4

2 に答える 2

2

すべてのイベントを処理する Java のメイン スレッドはGUI、イベント ディスパッチ スレッドまたは略して EDT と呼ばれます。したがって、EDT は、すべての要求を処理して提供できるように、常に解放しておく必要があります。EDT 内で無限ループを実行している場合、またはスリープなどの長時間実行タスクを実行している場合、すべての GUI イベントがブロックされます。UI がフリーズします。

コード内で 内で無限ループを実行しているactionListenerため、EDT はそのループ内に閉じ込められ、他の UI イベントを処理できません。

infinite loopこのような機能が必要な場合は、 SwingWorker.

SwingWorkerEDT を解放したまま、別のバックグラウンド スレッドで長時間実行されるタスクを実行できます。

button1 actionListenerこれは、を使用するためのコードですSwingWorker。これを貼り付けて見てください。唯一の問題はSwingWorker、スタートボタンをクリックするたびに新しいボタンが作成されることですが、クリックした後にボタンを無効にすることで簡単に修正できます

button1.addActionListener(new ActionListener()                                  
{                                                                               
    public void actionPerformed(ActionEvent e)                                  
    {                                                                           
        SwingWorker<Void, Void> sw = new SwingWorker<Void, Void>()              
        {                                                                       
            @Override                                                           
            protected Void doInBackground() throws Exception                    
            {                                                                   
                Robot robot = new Robot();                                      
                start = true;                                                   
                System.out.println("Pressed");                                  

                while (start)                                                   
                {                                                               
                    robot.keyPress(KeyEvent.VK_W);                              
                    Thread.sleep(1);                                            
                    robot.keyRelease(KeyEvent.VK_W);                            
                    Thread.sleep(150);                                          
                    robot.keyPress(KeyEvent.VK_S);                              
                    Thread.sleep(1);                                            
                    robot.keyRelease(KeyEvent.VK_S);                            
                    Thread.sleep(150);                                          
                    robot.keyPress(KeyEvent.VK_A);                              
                    Thread.sleep(1);                                            
                    robot.keyRelease(KeyEvent.VK_A);                            
                    Thread.sleep(150);                                          
                    robot.keyPress(KeyEvent.VK_D);                              
                    Thread.sleep(1);                                            
                    robot.keyRelease(KeyEvent.VK_D);                            
                    Thread.sleep(150);                                          
                }                                                               
                return null;                                                    
            }                                                                   
        };                                                                      
        sw.execute();                                                           
    }                                                                           
});
于 2013-05-26T03:15:13.953 に答える
0

私たちの目的はよくわかりませんRobotが、キー イベントをキャプチャしてそれに応答する最も簡単な方法は、キー バインディングAPIを使用することです。

GUI プログラミングとは、いつでもどのような順序で発生する可能性があるイベントにも対応することです。通常、イベントはオブザーバー パターンを使用して配信されます。つまり、興味を登録すると、イベントが発生したときに通知され、他に何もする必要はありません。

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ClickOfDeath {

    public static void main(String[] args) {
        new ClickOfDeath();
    }

    private KeyTask keyTask;
    private JTextArea textArea;

    public ClickOfDeath() {

        EventQueue.invokeLater(
                        new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JPanel buttons = new JPanel();

                final JButton type = new JButton("Start");
                type.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        textArea.requestFocusInWindow();
                        if (keyTask == null) {
                            type.setText("Stop");
                            keyTask = new KeyTask();
                            new Thread(keyTask).start();
                        } else {
                            keyTask.stop();
                            keyTask = null;
                            type.setText("Start");
                        }
                    }

                });

                JButton close = new JButton(new CloseAction());
                InputMap im = close.getInputMap(JButton.WHEN_IN_FOCUSED_WINDOW);
                ActionMap am = close.getActionMap();

                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
                am.put("escape", new CloseAction());

                buttons.add(type);
                buttons.add(close);

                textArea = new JTextArea(10, 20);
                textArea.setWrapStyleWord(true);
                textArea.setLineWrap(true);

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(textArea));
                frame.add(buttons, BorderLayout.SOUTH);
                frame.getRootPane().setDefaultButton(close);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public static class KeyTask implements Runnable {

        private volatile boolean keepRuning = true;

        @Override
        public void run() {
            try {
                Robot bot = new Robot();
                bot.setAutoDelay(40);
                while (keepRuning) {
                    bot.keyPress(KeyEvent.VK_SHIFT);
                    type(bot, KeyEvent.VK_S);
                    bot.keyRelease(KeyEvent.VK_SHIFT);
                    type(bot, KeyEvent.VK_W);
                    type(bot, KeyEvent.VK_I);
                    type(bot, KeyEvent.VK_N);
                    type(bot, KeyEvent.VK_G);
                    type(bot, KeyEvent.VK_SPACE);
                    type(bot, KeyEvent.VK_I);
                    type(bot, KeyEvent.VK_S);
                    type(bot, KeyEvent.VK_SPACE);
                    type(bot, KeyEvent.VK_A);
                    type(bot, KeyEvent.VK_W);
                    type(bot, KeyEvent.VK_E);
                    type(bot, KeyEvent.VK_S);
                    type(bot, KeyEvent.VK_O);
                    type(bot, KeyEvent.VK_M);
                    type(bot, KeyEvent.VK_E);
                    type(bot, KeyEvent.VK_PERIOD);
                    type(bot, KeyEvent.VK_PERIOD);
                    type(bot, KeyEvent.VK_PERIOD);
                }
            } catch (AWTException exp) {
                exp.printStackTrace();
            }
        }

        public void stop() {
            keepRuning = false;
        }

        protected void type(Robot bot, int keyCode) {
            bot.keyPress(keyCode);
            bot.keyRelease(keyCode);
        }

    }

    public class CloseAction extends AbstractAction {

        public CloseAction() {
            putValue(NAME, "Close");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.exit(0);
        }
    }
}

Swing はシングル スレッド環境です。つまり、Swing は独自のスレッドで実行されます。そのスレッドをブロックするアクションまたは操作は、Swing が新しいイベントを登録済みのリスナーにディスパッチするのを防ぎます。

Swing の同時実行性を確認する

于 2013-05-26T03:21:15.170 に答える