有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何通过按键和释放使循环开始和结束?

这是我的密码。。。如何使其工作,以便在用户按住按钮时运行循环,并在用户释放按钮时停止

public void nextPrimeNum()
{
    x = false;
    int b = 2;
    ArrayList<Integer> next = new ArrayList<Integer>();   
    while(x)
    {
        next = factors(b);
        if(next.size()==2)
        {
            System.out.println(b);
        }
        b++;
    }
    System.out.println("End");
}
public void keyPressed(KeyEvent e)
{
    if(e.getKeyCode() == 401)
    {
        x = true;
    }
}
public void keyRealesed(KeyEvent e)
{
    if(e.getKeyCode() == 402)
    {
        x = false;
    }
}

共 (2) 个答案

  1. # 1 楼答案

    GUI和多线程编程本质上是困难的
    因此,这是尽可能简单的,不会太多违反最佳实践

    你需要几样东西:

    • 一个单独的Thread用于打印素数:
      它的run方法永远循环,但在未按下空格键时暂停
      (有关更多信息,请参见Defining and Starting a Thread
    • 将从AWT的事件调度线程调用的KeyListener
      事件处理方法旨在快速完成,以便其他事件 (如移动、调整大小和关闭帧)仍然可以快速处理
      (见How to Write a Key ListenerThe Event Dispatch Thread了解更多信息)
    • 一个可见的GUI组件(JFrame),用于添加KeyListener
    • 两个线程之间的一些同步(通过synchronizednotifywait) 以便主打印在keyPressed上开始/继续 并暂停在keyReleased
      (详见Guarded Blocks
    • 通过调用initGUI初始化并启动整个GUI
      (详见Initial Threads

    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    
    public class Main implements Runnable, KeyListener {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(Main::initGUI);
        }
    
        private static void initGUI() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new JLabel("Press SPACE key for printing primes"));
            frame.pack();
            frame.setLocationRelativeTo(null); // center on screen
            frame.setVisible(true);
    
            Main main = new Main();
            frame.addKeyListener(main);
            Thread thread = new Thread(main);
            thread.start();
        }
    
        private boolean spaceKeyPressed;
    
        private boolean isPrime(int n) {
            for (int i = 2; i < n; i++) {
                if (n % i == 0)
                    return false;
            }
            return true;
        }
    
        @Override
        public void run() {
            for (int n = 2; /**/; n++) {
                while (!spaceKeyPressed) {
                    synchronized (this) {
                        try {
                            wait(); // waits until notify()
                        } catch (InterruptedException e) {
                            // do nothing
                        }
                    }
                }
                if (isPrime(n)) {
                    System.out.println(n);
                }
            }
        }
    
        @Override
        public void keyTyped(KeyEvent e) {
            // do nothing
        }
    
        @Override
        public synchronized void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                spaceKeyPressed = true;
                notifyAll(); // cause wait() to finish
            }
        }
    
        @Override
        public synchronized void keyReleased(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                spaceKeyPressed = false;
                notifyAll(); // cause wait() to finish
            }
        }
    }
    
  2. # 2 楼答案

    所以,答案是——这很复杂。它涵盖了广泛的主题,如并发性(一般)、GUI开发、特定API(Swing)的最佳实践,通过阅读各种教程(和实验)可以更好地更详细地介绍这些主题

    该示例提供了两种执行“循环”的方法(在CalculateWorker类的doInBackground方法中提供)

    您可以按住JButton或按住[kbd]空格[kbd]栏,两者都会导致“主循环”运行,并用结果更新JTextArea

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicBoolean;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    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.SwingWorker;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    public class Test {
    
        public static void main(String[] args) {
            new Test();
        }
    
        public Test() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private JTextArea ta;
            private CalculateWorker worker;
    
            public TestPane() {
                setLayout(new BorderLayout());
    
                ta = new JTextArea(20, 20);
                ta.setEditable(false);
                add(new JScrollPane(ta));
    
                worker = new CalculateWorker(ta);
    
                JButton btn = new JButton("Press");
                btn.getModel().addChangeListener(new ChangeListener() {
                    @Override
                    public void stateChanged(ChangeEvent e) {
                        System.out.println("...isRunning = " + worker.isRunning());
                        if (!worker.isRunning()) {
                            return;
                        }
                        System.out.println("...isPressed = " + btn.getModel().isPressed());
                        System.out.println("...isPaused = " + worker.isPaused());
                        if (btn.getModel().isPressed()) {
                            worker.pause(false);
                        } else {
                            worker.pause(true);
                        }
                    }
                });
    
                add(btn, BorderLayout.SOUTH);
                worker.execute();
    
                InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
                ActionMap am = getActionMap();
    
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "Space.released");
                im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true), "Space.pressed");
    
                am.put("Space.released", new CalculateAction(false, worker));
                am.put("Space.pressed", new CalculateAction(true, worker));
            }
    
            public class CalculateWorker extends SwingWorker<List<String>, String> {
    
                private AtomicBoolean run = new AtomicBoolean(true);
                private AtomicBoolean paused = new AtomicBoolean(false);
    
                private ReentrantLock pausedLocked = new ReentrantLock();
                private Condition pausedCondition = pausedLocked.newCondition();
    
                private JTextArea ta;
    
                public CalculateWorker(JTextArea ta) {
                    this.ta = ta;
                    pause(true);
                }
    
                public void stop() {
                    run.set(false);
                    pausedLocked.lock();
                    pausedCondition.signalAll();
                    pausedLocked.unlock();
                }
    
                public void pause(boolean pause) {
                    paused.set(pause);
                    pausedLocked.lock();
                    pausedCondition.signalAll();
                    pausedLocked.unlock();
                }
    
                public boolean isPaused() {
                    return paused.get();
                }
    
                public boolean isRunning() {
                    return run.get();
                }
    
                @Override
                protected List<String> doInBackground() throws Exception {
                    List<String> values = new ArrayList<>(256);
                    long value = 0;
                    System.out.println("!! Start running");
                    while (run.get()) {
                        while (paused.get()) {
                            System.out.println("!! I'm paused");
                            pausedLocked.lock();
                            try {
                                pausedCondition.await();
                            } finally {
                                pausedLocked.unlock();
                            }
                        }
                        System.out.println("!! Start loop");
                        while (!paused.get() && run.get()) {
                            value++;
                            values.add(Long.toString(value));
                            publish(Long.toString(value));
                            Thread.sleep(5);
                        }
                        System.out.println("!! Main loop over");
                    }
                    System.out.println("!! Run is over");
                    return values;
                }
    
                @Override
                protected void process(List<String> chunks) {
                    for (String value : chunks) {
                        ta.append(value);
                        ta.append("\n");
                    }
                    ta.setCaretPosition(ta.getText().length());
                }
    
            }
    
            public class CalculateAction extends AbstractAction {
    
                private boolean start;
                private CalculateWorker worker;
    
                public CalculateAction(boolean start, CalculateWorker worker) {
                    putValue(NAME, "Calculate");
                    this.start = start;
                    this.worker = worker;
                }
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    worker.pause(start);
                }
    
            }
    
        }
    
    }
    

    Is there a simpler solution?

    当然,我总是先寻找最难理解的解决方案(讽刺)

    虽然降低复杂性“可能”是可能的,但该示例提供了一些“最佳实践”概念,您最好学习和理解这些概念

    根据所使用的API,解决方案也可能有所不同,因此,对于特定的API选择,它是“最简单”的解决方案

    I wanted to do it from the console!

    Java不能做到这一点——它的控制台支持充其量只是初步的,不支持“按键/释放”操作的概念(因为它在单个线程中运行,否则就不可能做到)

    您可能会尝试“有些”解决方案,但它们需要一个链接到本机二进制文件的第三方库来实现,这将(可能)减少它将运行的平台数量