简体   繁体   中英

Java Thread Start-Stop-Start on same button click

I am creating a simple java program with a GUI built with the help of window builder. The GUI consists of just a button.

On button click,start a thread that will print to the random number infinitely until it is stopped by clicking the same button again.

Here is my code

LoopTest.java

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class LoopTest extends JFrame implements ActionListener {//******
    private JButton startB, stopB;
    private JTextArea oa;
    Start sta;

    public LoopTest(){
        super("Final Exam: Question ");

        Container c = getContentPane();
        c.setLayout(new FlowLayout());

        startB = new JButton("START"); c.add(startB);

        stopB = new JButton("STOP"); c.add(stopB);

        oa = new JTextArea(5,20); c.add(oa);
        c.add(new JScrollPane(oa));

        registerEvents();
        sta = new Start("Loop", oa);

    }
    public void registerEvents(){
        startB.addActionListener(
                new ActionListener(){
                    public void actionPerformed(ActionEvent ae){
                        if(startB.isEnabled() == true )
                            sta.setLoopFlag(true);
                        if(!sta.isAlive())
                            sta.start();
                        startB.setEnabled(false);

                    }
                }
        );

        stopB.addActionListener(
                new ActionListener(){
                    public void actionPerformed(ActionEvent ae){
                        if(stopB.isEnabled()==true){
                            sta.setLoopFlag(false);

                        }

                    }

        }

        );
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub

    }
    public static void main(String[] args){
        LoopTest app = new LoopTest();
        app.setSize(300,300);
        app.setLocationRelativeTo(null);
        app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        app.setVisible(true);
    }

}

Start.java

public class Start extends Thread {

private JTextArea ta;
    private boolean loopFlag;

    public Start(String name, JTextArea ta){
        super(name);
        this.ta = ta;
        ta.setText("");
        loopFlag = true;
    }
    public void run(){
        int num=0;
        while(true)
            while(loopFlag){
                num = 1+ (int)(Math.random()*100);
                ta.append(num + "\n");
            }
    }


    public void setLoopFlag(boolean value){
        loopFlag = value;
    }

}

Stop.java

public class Stop extends Thread {
    public Stop( String name ){
        super(name);
    }
    public void run(){

    }
}

Thanks in advance.

Your code breaks Swing threading rules as you're making mutational changes to Swing components off of the Swing event thread. Suggestions:

  • Never extend Thread. It's almost always better to implement Runnable and use the Runnable in a Thread.
  • Avoid making Swing calls, other than repaint() off of the Swing event thread.
  • Your while (true) is a "tight" loop -- it has no Thread.sleep within it, and that means that it risks typing up the CPU in its tight loop, something that can hamper your program and your computer.
  • Best to avoid using direct background threading altogether here as your code issue can be solved much more easily and cleanly by using a Swing Timer. Please check the Swing Timer Tutorial
  • You can easily start and stop this Timer by calling its start() and stop() methods.
  • I would also use a JList preferentially over a JTextArea since it can more easily handle large amounts of data.
  • I also like using AbstractActions rather than ActionListeners for my JButton, and this problem lends itself nicely to their use. You can create an Action for start and one for stop and simply swap out the button's actions.

For example:

import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class StartStop extends JPanel {
    private static final int TIMER_DELAY = 300;
    private StartAction startAction = new StartAction();
    private StopAction stopAction = new StopAction();
    private JButton button = new JButton(startAction);
    private DefaultListModel<Integer> model = new DefaultListModel<>();
    private JList<Integer> jList = new JList<>(model);
    private Timer timer = new Timer(TIMER_DELAY, new TimerListener());

    public StartStop() {
        JPanel btnPanel = new JPanel();
        btnPanel.add(button);

        jList.setFocusable(false);
        jList.setVisibleRowCount(10);
        jList.setPrototypeCellValue(100000);
        JScrollPane scrollPane = new JScrollPane(jList);

        setLayout(new BorderLayout());
        add(scrollPane, BorderLayout.CENTER);
        add(btnPanel, BorderLayout.PAGE_END);
    }

    private class TimerListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            int num = 1 + (int) (Math.random() * 100);
            model.addElement(num);
        }
    }

    private class StartAction extends AbstractAction {
        public StartAction() {
            super("Start");
            putValue(MNEMONIC_KEY, KeyEvent.VK_S);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            timer.start();
            button.setAction(stopAction);
        }
    }

    private class StopAction extends AbstractAction {
        public StopAction() {
            super("Stop");
            putValue(MNEMONIC_KEY, KeyEvent.VK_S);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            timer.stop();
            button.setAction(startAction);
        }
    }


    private static void createAndShowGui() {
        JFrame frame = new JFrame("Start Stop");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new StartStop());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM