PreciseChain
PreciseChain

Reputation: 1

How can I change my JLabel text multiple times with varying delays in a Java swing GUI correctly using Timer or Thread.sleep()

So, as can be seen from my code below, I'm trying to change my JLabel text to the following values after the following time increments in a java swing GUI, but when I press the start button. Everything just freezes and the Label goes from the original text to the final text, "The game will continue for 20 seconds and now begins", how can I show all the intermediate texts too with the appropriate time delays?

    JLabel displayNum=new JLabel("Welcome to Mania Marauders");
        JButton b=new JButton("start");
        b.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                displayNum.setText("Soon, where this text appears, a number will appear");
                try {
                    Thread.sleep(1100);
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                displayNum.setText("This number correlates to a button below with the same number");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                displayNum.setText("If you're able to hit the right button before the number displayed changes, you get a point");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                displayNum.setText("The game will continue for 20 seconds and now begins");
            }
            
        });

Upvotes: 0

Views: 351

Answers (2)

Andrew Thompson
Andrew Thompson

Reputation: 168825

Establish a Swing Timer with a delay of 100 milliseconds. Create an ActionListener which declares an int count = 0; when constructed. In the actionPerformed(..) method, increment the count by one, then when it reaches 10, 17 and 37, take action to change the text and/or stop the Timer.

Upvotes: 3

Gilbert Le Blanc
Gilbert Le Blanc

Reputation: 51515

I created the following GUI. I used a JTextArea, rather than a JLabel.

Timed Text Display

You can't tell from a picture, but the messages display in order for a period of time.

To do this, I used a Runnable inside of a Thread. By using a Thread, I was able to process the messages without blocking the Event Dispatch Thread of the GUI.

Here's the complete runnable code.

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class TimedTextDisplay implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TimedTextDisplay());
    }
    
    private JTextArea textArea;
    
    private Messages messages;
    
    public TimedTextDisplay() {
        this.messages = new Messages();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Timed Text Display");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        frame.add(createMainPanel(), BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new BorderLayout(5, 5));
        panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        
        textArea = new JTextArea(3, 40);
        textArea.setEditable(false);
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);
        panel.add(textArea, BorderLayout.CENTER);
        
        JButton button = new JButton("Start");
        button.addActionListener(new ButtonListener());
        panel.add(button, BorderLayout.AFTER_LAST_LINE);
        
        return panel;
    }
    
    public class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {
            new Thread(new DisplayTextRunnable()).start();
        }
        
    }
    
    public class DisplayTextRunnable implements Runnable {

        @Override
        public void run() {
            for (MessageText text : messages.getMessages()) {
                setText(text.getText());
                sleep(text.getDelay());
            }
        }
        
        private void setText(String text) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    textArea.setText(text);
                }
            });
        }
        
        private void sleep(long duration) {
            try {
                Thread.sleep(duration);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
    }
    
    public class Messages {
        
        private final List<MessageText> messages;
        
        public Messages() {
            this.messages = new ArrayList<>();
            messages.add(new MessageText(3100, "Soon, where this text "
                    + "appears, a number will appear"));
            messages.add(new MessageText(2700, "This number correlates "
                    + "to a button below with the same number"));
            messages.add(new MessageText(4000, "If you're able to hit "
                    + "the right button before the number displayed "
                    + "changes, you get a point"));
            messages.add(new MessageText(1000, "The game will continue "
                    + "for 20 seconds and now begins"));
        }

        public List<MessageText> getMessages() {
            return messages;
        }
        
    }
    
    public class MessageText {
        
        private final long delay;
        
        private final String text;

        public MessageText(long delay, String text) {
            this.delay = delay;
            this.text = text;
        }

        public long getDelay() {
            return delay;
        }

        public String getText() {
            return text;
        }
        
    }

}

Upvotes: 3

Related Questions