单击同一按钮上的Java Thread Start-Stop-Start [英] Java Thread Start-Stop-Start on same button click

查看:58
本文介绍了单击同一按钮上的Java Thread Start-Stop-Start的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个简单的Java程序,该程序具有在window builder的帮助下构建的GUI.GUI只包含一个按钮.

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.

这是我的代码

LoopTest.java

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

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

Stop.java

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

    }
}

谢谢.

推荐答案

当您在Swing事件线程之外对Swing组件进行突变时,您的代码将破坏Swing线程规则.建议:

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

  • 从不扩展线程.最好总是实现Runnable并在线程中使用Runnable.
  • 避免在Swing事件线程之外进行除 repaint()之外的Swing调用.
  • 您的 while(true)是一个紧密"循环-里面没有 Thread.sleep ,这意味着您可能会在其中键入CPU其紧密的循环,可能会妨碍您的程序和计算机.
  • 最好避免在此处完全使用直接后台线程,因为使用Swing计时器可以更轻松,更轻松地解决您的代码问题.请检查 Swing Timer教程
  • 您可以通过调用其 start() stop()方法轻松地启动和停止此Timer.
  • 与JTextArea相比,我还将优先使用JList,因为它可以更轻松地处理大量数据.
  • 我还喜欢为JButton使用AbstractActions而不是ActionListeners,并且此问题非常适合它们的使用.您可以为开始创建一个动作,为停止创建一个动作,只需换出按钮的动作即可.
  • 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.

例如:

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

这篇关于单击同一按钮上的Java Thread Start-Stop-Start的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆