0

When I try to use any kind of delay on my code the program gets delayed but the JLabel that was put before the delay gets updated after the program ends.

I want the program to:

  • update the JLabel on the GUI
  • wait for 5 seconds
  • update the JLabel again with diferent text
  • wait another 5 seconds

I have tried with timers, invokelater, invokeandwait, thread.sleep and others.

The problems is that the GUI does get delayed at the right spot but the GUI does not update the JLabel ath place where the code is located. The JLabel gets updated after the program ends.

I want the user to be able to read the text for 5 seconds then read another text for another 5 seconds in order. I do not want the program to run the gui pause at a cetain spot then at end just update the JLabel. I want the gui to get updated before the delay. I do not want the same thing that when I used a timer to happen where I type in a setText for the JLabel before the Timer is typed and then when I run the program the timer works but the JLabel gets updated after the delay(It is not what I want).

jhamon
  • 3,603
  • 4
  • 26
  • 37

1 Answers1

1

The way to achieve that is either using a Swing Worker, either a a Swing Timer. A Swing worker runs a task in background and at the same time it is capable of publishing GUI changes in the Event dispatch thread (the thread where the GUI runs). A SwingTimer can be considered as a simplified version of a Swing Worker, that only runs a task after some time in the Event Dispatch Thread. (Consider a worker that sleeps the thread in background, and after the sleep, it runs the task in the Gui thread).

There are a lot of examples online, like this one and this one.

If you do not want to do something in background, a Timer solution sounds "simpler". Take a look at How can I pause/sleep/wait in a java swing app?

An example where it is closer to what you need (with a worker):

public class WorkerExample extends JFrame {
    private static final long serialVersionUID = 6230291564719983347L;
    private JLabel label;

    public WorkerExample() {
        super("");
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        setLayout(new FlowLayout());

        SwingWorker<Void, String> worker = new SwingWorker<Void, String>() {

            @Override
            protected Void doInBackground() throws Exception {
                publish("Started....");
                Thread.sleep(1500);
                for (int i = 0; i < 5; i++) {
                    publish("Number of iterations: " + i);
                    //Do something
                    Thread.sleep(3500);
                }
                return null;
            }

            @Override
            protected void process(List<String> chunks) {
                String chunk = chunks.get(0);
                label.setText(chunk);
            }

            @Override
            protected void done() {
                label.setText("Done.");
            }
        };

        JButton button = new JButton("Start");
        button.addActionListener(e -> worker.execute());
        add(button);

        label = new JLabel("Nothing yet.");
        add(label);

        setSize(400, 400);
        setLocationByPlatform(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new WorkerExample().setVisible(true);
        });
    }
}

You can experiment with these in order to understand how a SwingWorker works, but I strongly recommend you to read concurrency in Swing before doing that.

George Z.
  • 6,643
  • 4
  • 27
  • 47