简体   繁体   中英

How do I make a delay in a GUI that works separately from the other delay Java

package Login;
import java.awt.BorderLayout;    
import java.awt.event.ActionEvent;    
import java.awt.event.ActionListener;        
import java.io.IOException;    
import javax.swing.JButton;       
import javax.swing.JFrame;    
import javax.swing.JLabel;    
import javax.swing.JTextArea;  

public class GUI {

    public static void main(String[] args) {
        JLabel label = new JLabel("Delay");
        JFrame jarvis = new JFrame("JARVIS");
        jarvis.setSize(400, 400);
        jarvis.setLocation(500,250);
        label.setBounds(50,50,200,40);
        final JTextArea textArea = new JTextArea(10, 40);
        jarvis.getContentPane().add(BorderLayout.CENTER, textArea);
        final JButton button = new JButton("Activate Jarvis");
        jarvis.getContentPane().add(BorderLayout.NORTH, button);
        button.addActionListener(new ActionListener() {



            @Override
            public void actionPerformed(ActionEvent e) {

                try {
                    Login.jSpeech("/Users/C21/Desktop/JARVISSpeech/Ready.wav");
                } catch (IOException e1) {
                    e1.printStackTrace();
                }

                long now = System.currentTimeMillis();
                long later = now + 1000;
                while (System.currentTimeMillis() < later) {
                    int i = 0;
                    i++;
                }

                textArea.append("Uploading JARVIS...\n");

                 now = System.currentTimeMillis();
                 later = now + 1000;
                while (System.currentTimeMillis() < later) {
                    int i = 0;
                    i++;
                }

                textArea.append("Logged In...\n");


        }
    });


    jarvis.setVisible(true);



    }

}

Instead of waiting 1000ms and saying "Uploading Jarvis", it waits 2000ms then says "Uploading Jarvis" & "Logging In" simultaneously. I need the timers to work separately. The other types I tried also ended up failing like this. The other ones I tried worked if it wasn't in the GUI thingy. The thing says add more details so here I am saying random stuff.

First, instead of that:

        long later = now + 1000;
        while (System.currentTimeMillis() < later) {
            int i = 0;
            i++;
        }

You should rather use Thread.sleep(1000)

Second issue:

When ActionListener's public void actionPerformed(ActionEvent e) { is called, whole body is executed. Since you have 2 waiting loops, 1000s each inside, you will wait 2 seconds. Change that.

Third and last and most important: Never ever sleep or wait or do heavy stuff in Event Dispatch Thread - EDT ( actionPerformed is executed by EDT). By doing so, you will make your appication freeze during that operation/wait/sleep. If you need to do something in background, there is dedicated solution for that: SwingWorker . If you want to wait and do some action after that, in Swing you can use Timer

Executing asynchronous code in a Swing UI requires it to be executed in a separate Thread . This can be done be either creating a new Thread or using an existing ExecutorService .

Note that updates to the UI must be run in the Event Dispatch Thread - this can be acomplished by using either SwingUtilities.invokeLater(..) or SwingUtilities.invokeAndWait(..)

Example code:

Runnable runnable = () -> {

    // execute asynchronous code
    try {
        // wait for 1000ms = 1sec
        Thread.sleep(1000);
    } catch (InterruptedException ex) {
        ex.printStackTrace();
    }

    SwingUtilities.invokeLater(() -> {
        // update UI
    });
};

Thread thread = new Thread(runnable);
thread.setDaemon(true);
thread.start();

Alternatively you can use a ScheduledExecutorService with a fixed thread pool (that you can create once for your application and then reuse). The ScheduledExecutorService allows to schedule code that is to be run after a given delay :

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

Runnable runnable = () -> {
    // execute asynchronous code
    SwingUtilities.invokeLater(() -> {
        // update UI

    });
};

scheduledExecutorService.schedule(runnable, 1, TimeUnit.SECONDS);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM