【问题标题】:Java Thread Start-Stop-Start on same button clickJava Thread Start-Stop-Start on同一个按钮单击
【发布时间】:2016-12-27 17:06:14
【问题描述】:

我正在创建一个简单的 java 程序,其 GUI 是在窗口生成器的帮助下构建的。 GUI 只包含一个按钮。

单击按钮时,启动一个线程,该线程将无限打印到随机数,直到再次单击同一按钮将其停止。

这是我的代码

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(){

    }
}

提前致谢。

【问题讨论】:

  • 您的问题是什么?您不能通过简单地“替换对它的引用”来停止线程。 Start 永远不会因为外部(无用)循环而停止。请提出一个不言自明的问题,可能是 [mvce]。

标签: java multithreading swing button concurrency


【解决方案1】:

当您从 Swing 事件线程对 Swing 组件进行突变更改时,您的代码会破坏 Swing 线程规则。 建议:

  • 永远不要扩展线程。实现 Runnable 并在线程中使用 Runnable 几乎总是更好。
  • 避免在 Swing 事件线程之外进行 Swing 调用,repaint() 除外。
  • 您的while (true) 是一个“紧密”循环——其中没有Thread.sleep,这意味着它可能会在紧密循环中输入CPU,这可能会妨碍您的程序和计算机。
  • 最好避免在此处完全使用直接后台线程,因为使用 Swing Timer 可以更轻松、更干净地解决代码问题。请查看Swing Timer Tutorial
  • 您可以通过调用它的start() 和stop() 方法轻松地启动和停止这个定时器。
  • 我也会优先使用 JList 而不是 JTextArea,因为它可以更轻松地处理大量数据。
  • 我还喜欢在我的 JButton 中使用 AbstractActions 而不是 ActionListeners,这个问题非常适合使用它们。您可以为开始创建一个动作,为停止创建一个动作,然后简单地交换按钮的动作。

例如:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 2010-12-08
    相关资源
    最近更新 更多