Java Sleep not working in loop [closed]

百般思念 提交于 2019-12-02 12:24:01

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...

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

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!