Java Swing cancels endless loop

I ran into an infinite loop problem in Swing. We did some research and stumbled upon SwingWorker threads, but are not quite sure how to implement them. I hit a simple program that shows the problem. One button starts an infinite loop, and I want the other button to stop it, but, of course, due to a problem with one Swing thread, the other button froze. The code below will help evaluate: -

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); } } 
+4
source share
4 answers

You can do this easily without running 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 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); } } 

As your Model.go () works in a separate thread, the Stream Event Manager can freely perform its actions, for example, hanging with a button down.

There is a catch! , because the Model.go () stream will work wildly! It actually called as many times per second as your system could be.

If you plan to implement some animation or something similar, you will need:

  • use a timer

or

Example, if you go on topics:

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

As you can see, I added Thread.sleep (1500) to 1500 in milliseconds (1.5 seconds). Thread.sleep may be interrupted for some reason, so you should catch an InterruptedException .

You don't need to handle InterruptedException deeper in this particular case, but if you're interested, you can read this nice article .

+3
source

You are blocking the Event Dispatch Thread (EDT). The thread is responsible for processing images and other requests related to the user interface. When the EDT is locked, the user interface will become frozen because it cannot handle any events. See the Dispatch Thread tutorial for more information .

Consider using timers ( How to use Swing timers ), SwingWorker or an auxiliary background thread. The background thread can communicate with EDT using SwingUtilities.invokeLater() . This mechanism is already implemented in SwingWorker , so it can be easier with it. It depends on the required functionality.

+3
source

Use javax.swing.Timer to do go() work once (with some additional delay), using start() and stop() in event handling.

+3
source

I decided to use the SwingWorker thread, and below is the updated controller class. It does what I need, but my question is, is it correct and is it pure code? In addition, I tried to get the output of the model.go () method into the text box of the view according to the commented lines, but was not successful, does anyone know how?

 public class Controller implements ActionListener { private Model theModel; private View theView; private SwingWorker<Void, Void> worker; 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.setGo(true); worker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() { // theView.setMessageArea(theModel.getCounterToString()); return theModel.go(); } @Override protected void done() { // theView.setMessageArea(theModel.getCounterToString()); } }; worker.execute(); } else if(buttonClicked.equals(theView.getCancelButton())) { theModel.setGo(false); } } } public class Model { public Void go() { counter = 0; while(go) { counter++; System.out.println(counter); } return null; } 
0
source

Source: https://habr.com/ru/post/1445271/


All Articles