2

I want to display a text before executing the function mediaPlayer(). During the execution of the mediaplayer, I sleep the thread. That's ok because nothing needs to happen then (then just need to listen).

However, the last text: "Listen to...", is not being displayed (except with a few seconds delay). It there a way to flush the jFrame first before the thread goes to sleep?

 expText.setText("Listen to the song and give a rating when it finishes.");

                    startButton.setEnabled(false);


                    //play sound
                    try {
                        mediaPlayer();
                        //wait for the duration of the stimuli
                        Thread.sleep(stimDuration);
                    ...
dorien
  • 5,265
  • 10
  • 57
  • 116
  • Yes: Don't ever do long-running operations on the UI thread. Call `mediaPlayer` on a background thread or rewrite it to be asynchronous. – Dark Falcon Feb 09 '15 at 19:28
  • 1
    You don't want to wrap the SwingWorker in a Timer, that's just...weird. Just use the SwingWorker to play the audio. Take a look at [this example](http://stackoverflow.com/questions/24274997/java-wav-player-adding-pause-and-continue/24275168#24275168) – MadProgrammer Feb 09 '15 at 20:23
  • Whats mediaPlayer and dhow does it work? What's the purpose of the delay? – MadProgrammer Feb 09 '15 at 20:28

2 Answers2

2

The setText won't display until the EDT renders another frame, which it can't do because it's busy sleeping for stimDuration amount of time.

Try to play the sound on a separate thread, play the sound on some other thread, detect when the sound stops, and then do another action on the EDT where you change expText back to the original text that you had.

NESPowerGlove
  • 5,496
  • 17
  • 28
  • There's no way to get around this without explicitely defining multithreading? I am not an expert in this, that's why I ask. I just want the program to wait a little. Swing timer seemed an option too, but I couldn't figure it out. – dorien Feb 09 '15 at 19:31
  • @dorien Perhaps use something like this http://stackoverflow.com/a/782309/3352285 to avoid explicitly creating and handlingThreads and Runnables yourself. – NESPowerGlove Feb 09 '15 at 19:35
  • Thank, I just tried that, but in the done() method, I can't access my startButton because it's in a different class. – dorien Feb 09 '15 at 19:47
  • @dorien Can't you create an anonymous class instance of it right there on the spot where you already can access your startButton? – NESPowerGlove Feb 09 '15 at 19:52
  • I've updated my answer with what I have tried. But I'm not doing it right – dorien Feb 09 '15 at 19:57
  • Actually I'm also thinking it's still sleeping the thread, so it might be the same problem. – dorien Feb 09 '15 at 19:58
  • Oh, maybe I could do this in the audioplayer function, something with AudioPlayer.player.start(audioStream); AudioPlayer.player.getState(); – dorien Feb 09 '15 at 20:02
  • Yeah your syntax isn't right at all, looks like you are halfway through defining a timer and then you try to define an anonymous class. Look at how such a class is defined here: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/simple.html, at the end, at the closing brace `}`, call the execute method like the first link I showed you does. – NESPowerGlove Feb 09 '15 at 20:11
  • Thank, I will look at it. I wonder if something like this.repaint(); could just refresh the frame before putting the thread to sleep – dorien Feb 09 '15 at 20:18
  • @dorien There's one thread, the EDT, that handles actions that are queued for Swing. If the EDT is currently executing the code that goes to sleep, then itself is going to sleep, which means it's not going to execute that repaint. – NESPowerGlove Feb 09 '15 at 20:22
  • I implemented the threads (and updated my question). That works at least for the showing of the text. Now the buttons need to be activated after the audio stops playing. Unfortunately, t1 thread stops before that. Thanks so much already for your help – dorien Feb 09 '15 at 20:40
1

The following combined use of Threads and Swing Timer solved the problem.

            Thread t2 = new Thread(new Runnable() {
                        public void run() {
                            try {
                                startButton.setEnabled(false);
                                startButton.setVisible(false);
                                buttonsPanel.setEnabled(false);
                                buttonsPanel.setVisible(false);
                                expText.setText("Listen to the song and give a rating when it finishes.");
                            } catch (Exception e1) {
                                e1.printStackTrace();
                            }
                        }
                    });
                    t2.start();




                    Thread t1 = new Thread(new Runnable() {
                        public void run() {
                            // code goes here.
                            try {
                                mediaPlayer();
//                               Thread.sleep(5000);


                            } catch (Exception e1) {
                                e1.printStackTrace();
                            }
                        }
                    });
                    t1.start();

                    ActionListener taskPerformer = new ActionListener() {
                        public void actionPerformed(ActionEvent evt) {
                            //...Perform a task...

                            resultButtonGroup.clearSelection();
                            startButton.setEnabled(true);
                            startButton.setVisible(true);
                            buttonsPanel.setVisible(true);

                        }
                    };
                    Timer timer = new Timer(stimDuration ,taskPerformer);
                    timer.setRepeats(false);
                    timer.start();
dorien
  • 5,265
  • 10
  • 57
  • 116