Java Swing取消无限循环 [英] Java Swing cancelling an Infinite loop

查看:120
本文介绍了Java Swing取消无限循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了Swing中的无限循环问题。完成了一些研究并遇到了SwingWorker线程,但并不确定如何实现它们。我已经敲了一个简单的程序来显示问题。一个按钮启动无限循环,我希望另一个按钮停止它,但当然由于Swing单线程问题,另一个按钮已冻结。代码如下并帮助赞赏: -

I've hit the infinite loop problem in Swing. Done some research and come across SwingWorker threads but not really sure how to implement them. I've knocked together a simple program that shows the problem. One button starts the infinite loop and I want the other button to stop it but of course due to the Swing single thread problem the other button has frozen. Code below and help appreciated:-

public class Model
{
    private int counter;
    private boolean go = true;

    public void go()
    {
        counter = 0;

        while(go)
        {
            counter++;
            System.out.println(counter);
        }
    }

    public int getCounter()
    {
        return counter;
    }

    public void setGo(boolean value)
    {
        this.go = value;
    }
}

public class View extends JFrame
{
    private JPanel                  topPanel, bottomPanel;
    private JTextArea               messageArea;
    private JButton                 startButton, cancelButton;
    private JLabel                  messageLabel;
    private JScrollPane             scrollPane;

    public View()
    {
        setSize(250, 220);
        setTitle("View");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        topPanel = new JPanel();
        bottomPanel = new JPanel();
        messageArea = new JTextArea(8, 20);
        messageArea.setEditable(false);
        scrollPane = new JScrollPane(messageArea);
        messageLabel = new JLabel("Message Area");
        topPanel.setLayout(new BorderLayout());
        topPanel.add(messageLabel, "North");
        topPanel.add(scrollPane, "South");
        startButton = new JButton("START");
        cancelButton = new JButton("CANCEL");
        bottomPanel.setLayout(new GridLayout(1, 2));
        bottomPanel.add(startButton);
        bottomPanel.add(cancelButton);
        Container cp = getContentPane();
        cp.add(topPanel, BorderLayout.NORTH);
        cp.add(bottomPanel, BorderLayout.SOUTH);
    }

    public JButton getStartButton()
    {
        return startButton;
    }

    public JButton getCancelButton()
    {
        return cancelButton;
    }

    public void setMessageArea(String message)
    {
        messageArea.append(message + "\n");
    }
}


public class Controller implements ActionListener
{
    private Model theModel;
    private View  theView;

    public Controller(Model model, View view)
    {
        this.theModel = model;
        this.theView = view;
        view.getStartButton().addActionListener(this);
        view.getCancelButton().addActionListener(this);
    }

    public void actionPerformed(ActionEvent ae)
    {
        Object buttonClicked = ae.getSource();
        if(buttonClicked.equals(theView.getStartButton()))
        {
            theModel.go();
        }
        else if(buttonClicked.equals(theView.getCancelButton()))
        {
            theModel.setGo(false);
        }
    }
}



public class Main
{
    public static void main(String[] args)
    {
        Model model = new Model();
        View view = new View();
        Controller controller = new Controller(model, view);
        view.setVisible(true);
    }
}


推荐答案

你无需实现任何计时器即可轻松完成,您只需在 actionPerformed 方法中添加两行:

You can do it easily without implementing any timer, you just need to add two lines to your actionPerformed method:

public void actionPerformed(ActionEvent ae)
{
    Object buttonClicked = ae.getSource();
    if(buttonClicked.equals(theView.getStartButton()))
    {
      theModel.setGo(true); //make it continue if it's just stopped
      Thread t = new Thread(new Runnable() { public void run() {theModel.go();}}); //This separate thread will start the new go...
      t.start(); //...when you start the thread! go!
    }
    else if(buttonClicked.equals(theView.getCancelButton()))
    {
        theModel.setGo(false);
    }
}

作为 Model.go()正在一个单独的线程中运行,事件调度线程可以自由地执行其操作,例如再次释放按钮,而不是按下按钮。

As your Model.go() is running in a separate thread, the Event Dispatch Thread is free to do its stuff, like drawing the button released again, instead of hanging with the button down.

有一个问题! 但是,因为运行 Model.go()的线程将运行 疯狂! ,它几乎被称为系统可以每秒多次。

There's a catch! however, because the thread running Model.go() will run wildly!, it's virtually called as many times per second as your system can.

如果您打算实施某些动画等,那么您将需要:

If you plan to implement some animation or the like, then you will need to:


  • 使用计时器,

  • add some sleep time to the new thread.

如果您选择线程示例:

public void go()
{
    counter = 0;
        while(go)
    {
        counter++;
        System.out.println(counter);
        try {
            Thread.sleep(1500); //Sleep for 1.5 seconds
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

如你所见,我添加了 Thread.sleep(1500)以1500毫秒(1.5秒)为时间。由于某些原因,Thread.sleep可能会被中断,因此您必须捕获 InterruptedException

As you can see I added Thread.sleep(1500) being 1500 the time in milliseconds (1.5 seconds). Thread.sleep can be interrupted for some reasons, so you must catch the InterruptedException.

没有必要更深入地正确处理 InterruptedException 在这种特殊情况下,如果您对此感到好奇,可以阅读好文章

It's not necessary to go deeper on handling correctly the InterruptedException in this particular case, but if you feel curious about it you can read this nice article.

这篇关于Java Swing取消无限循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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