Java Sleep not working in loop [closed]

2019-03-03 16:59发布

问题:

What I want to do in my java program is, that when I press the button it displays text in textfield in intervals of time. i.e I press the button then a jFrame pops up and there is a label which shows text like: 1st second:"1st" then a time lag of say 1 sec then 2nd thing: "2nd"

I am a newbie and I tried to Google this problem but I couldn't find a solution even after 3-4 hours I tried a lot of things: sleep, try n catch...

Please write the answer very simplified.

Here is my code: In the following code, when the button is pressed, the jFrame comes but has a white screen in it and when the sum ends, its screen turns grey and it shows the answer....

   private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    See.setVisible(true);//See is the JFrame   
    t007.setVisible(true);//Label in See
    l2.setVisible(true);//TextField in See
    int ran, g, d, col, ran2;
    double y = 1000 * (Double.parseDouble(t2.getText()));
    int x = (int) y;
    d = 0;
    double c = Math.pow(10, Integer.parseInt(t1.getText()));
    col = Integer.parseInt(t3.getText());
    for (g = 0; g < col;) {
        ran = (int) (Math.random() * (c)); // Random Number Creation Starts
        if (ran > (c / 10)) {
            g = g + 1;
            ran2 = ((int) (Math.random() * 10)) % 2;
            if (ran2 == 1) {
                ran = ran * (-1);
            }
            d = d + ran;
            if (d < 0) {
                ran = ran * (-1);
                d = d + (2 * ran);
            }
            l2.setVisible(true);
            t007.setText("" + ran);
            System.out.println("" + ran);
            jButton6.doClick();
            //Pausing (Sleep)
            try {
                  Thread.sleep(x);

             } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
            }
            }
            }
             l2.setText("" + d);
               }                                        

回答1:

Swing is a single threaded framework, that is, all interactions and modifications to the UI are expected to occur within the context of the Event Dispatching Thread.

The EDT is responsible for, amongst other things, processing repaint requests.

Anything that stops the EDT from running (like Thread.sleep and looping for a long time) will prevent it from processing the events, virtually "hanging" your application until it becomes unblocked...

Now, I tried to decipher what you program was trying to do...but failed, so instead...I made a pretty counter...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TickOver {

    public static void main(String[] args) {
        new TickOver();
    }

    public TickOver() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextField field;
        private JButton button;
        private int tick; 
        private Timer timer;

        public TestPane() {

            field = new JTextField(10);
            field.setEditable(false);
            button = new JButton("Start");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    button.setEnabled(false);
                    tick = 0;
                    timer.start();
                }
            });

            timer = new Timer(1000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    field.setText(Integer.toString(++tick));
                    if (tick > 4) {
                        timer.stop();
                        button.setEnabled(true);
                    }
                }
            });
            timer.setInitialDelay(0);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(field, gbc);
            add(button, gbc);

        }
    }
}

Take a close look at Concurrency in Swing for more details...



回答2:

You should never sleep in UI thread, as it make the UI lag. As if the process takes time to complete the UI will get stuck and user experience will get hurt.

Use other mechanisms such as a Timer or SwingWorker

Concurrency in Swing



回答3:

It's very bad practice to sleep the user interface thread. (As this will cause the application to become unresponsive.) You ought to put all this code inside the Run() method of a Runnable instance:

java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                // Your code here.
            }
        });


回答4:

The problem is that you run your long running loop on the event dispatch thread. But this is the thread that must dispatch all events of the application like mouse or keyboard events but also repaint events that causes your user interface to get repainted every time it gets 'dirty'. That means, while your for-loop is running, the user interface is not repainted nor are any other events processed. Your UI freezes! Your jButton5ActionPerformed method should return as soon as possible so that the event dispatch thread can process other events. Your long running operation should be run by a separate thread in the background.

A good starting point is the following tutorial about concurrency in Swing: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/

Maybe you can use the SwingWorker class to perform your background work: http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html