|
-
May 6th, 2010, 09:25 AM
#1
Repeating a SwingWorker
I'm using a SwingWorker to seperate a loop in my code which plays a midi sound. However I need to use the SwingWorker more than once and there's no way of telling how many times it will need to be repeated as its executed on a button click.
Here is the method which uses the SwingWorker:
Code:
public void playTune() {
//Play tune swing worker
SwingWorker<TunePlayer, Void> playWorker = new SwingWorker<TunePlayer, Void>() {
@Override
protected TunePlayer doInBackground() throws Exception {
while (!stopTune) {
if (!player.isPlaying()) {
player.play(tune);
}
}
return null;
}
};
playWorker.execute();
}
I understand that doInBackground() can only be executed once but here I am making a new object every time that button is pressed (playTune() is fired when the button is clicked). Equally I should mention that there is a stop button which turn stopTune to true when it is clicked. Any help would be much appreciated
-
May 6th, 2010, 11:13 AM
#2
Re: Repeating a SwingWorker
Why are you using SwingWorker to provide the background execution?
The advantage of using a SwingWorker over creating your own background thread is it simplifies the task of updating the GUI from the background thread. You don't appear to be updating the GUI from the background thread so you probably don't need to use SwingWorker.
-
May 6th, 2010, 12:32 PM
#3
Re: Repeating a SwingWorker
The program does use Swing for GUI and as said these are triggered on a button click. I've tried using ordinary threads with this but as soon as you press play the whole program freezes. The loop works as you can hear the sound looping round but obviously you can't do anything and you can't even press the stop button.
SwingWorker seems to do fine as it does exactly what I want it to except for the fact that I can't run it more than once.
-
May 6th, 2010, 12:40 PM
#4
Re: Repeating a SwingWorker
SwingWorker provides a mechanism for you to interact with the GUI from the background thread - you are not doing this hence you do not need a SwingWorker. What you are doing is running a time consuming task and don't want the GUI to freeze whilst the task it is running, therefore you need to run it on a background thread ie not the Event Dispatch Thread. You do not need a SwingWorker to do this, you just need to create your own thread and run the task on that.
-
May 6th, 2010, 12:46 PM
#5
Re: Repeating a SwingWorker
I guess I understand that but I have already tried creating my own thread and running it from there and it still freezes the application. I've still got the code for the thread class if you need to see what I did?
-
May 6th, 2010, 12:54 PM
#6
Re: Repeating a SwingWorker
Ok, by all means post the code so we can tell you what is wrong with it.
What I would do is create a Runnable object to play the sound, create a single thread ExecutorService object by calling Executors.newSingleThreadExecutor() and then every time I wanted to play the sound submit the Runnable to the ExecutorService object.
-
May 6th, 2010, 01:04 PM
#7
Re: Repeating a SwingWorker
Ok here is the thread class that I created a while back. In the other class where the SwingWorker is it was replaced with:
Code:
Thread playerThread = new Thread(new LoopsPlayer(tune, player));
playerThread.run();
The thread class code is:
Code:
public class LoopsPlayer implements Runnable {
private boolean stopTune;
private Tune tune;
private TunePlayer player;
public LoopsPlayer(Tune tune, TunePlayer player) {
this.tune = tune;
this.player = player;
}
public void setStopTune(boolean stop) {
stopTune = stop;
}
@Override
public void run() {
while (!stopTune) {
if (!player.isPlaying()) {
player.play(tune);
}
}
}
}
-
May 6th, 2010, 01:15 PM
#8
Re: Repeating a SwingWorker
Your code is creating a background thread with a Runnable object but is then directly calling the run() method from the Event Dispatch Thread ie you aren't using the background thread the play the sound. To use the background thread you need to call it's start() method and not the run() method.
This of course will still be a one shot object because you can't restart a thread once it has completed. That's why I suggested you create an ExecutorService.
-
May 6th, 2010, 01:18 PM
#9
Re: Repeating a SwingWorker
So basically what you're saying is its going to be no different from what I'm trying to do now? I've never actually heard of an ExecutorService, looks like I'll need to look that one up
-
May 6th, 2010, 01:28 PM
#10
Re: Repeating a SwingWorker
Look in the java.util.concurrent package
-
May 6th, 2010, 01:35 PM
#11
Re: Repeating a SwingWorker
You would use it as follows:
Code:
ExecutorService exec = Executors.newSingleThreadExecutor();
Runnable player = new Runnable()
{
@Override
public void run()
{
// play sound code
}
};
...
// place this line in your action listener to play the sound every time it is executed
exec.submit(player);
-
May 6th, 2010, 01:37 PM
#12
Re: Repeating a SwingWorker
Ok thanks I'll give this a try
-
May 6th, 2010, 01:57 PM
#13
Re: Repeating a SwingWorker
Worked perfectly and does everything I wanted, many thanks for your help! I only have one last question, when the loop ends and it exits the run() method is the thread cleared up as normal? In other words if I click start, stop then start again I'm not using 2 different threads am i? I don't want it to end up creating like 20 threads or anything silly
-
May 6th, 2010, 02:45 PM
#14
Re: Repeating a SwingWorker
The thread stops when the run() method finishes. It's the approved way of stopping it.
I think there is a world market for maybe five computers...
T. J. Watson (IBM)
Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.
-
May 6th, 2010, 03:09 PM
#15
Re: Repeating a SwingWorker
If you are using an ExecutorService then a single thread (or pool of threads depending on the type of Executor service you have created), is kept alive by the ExecutorService object to run the tasks you submit to it, until you call one of its shutdown methods.
So to answer your question, if you keep the same ExecutorService alive to play the sounds as and when you need them then it will reuse the thread(s) it has, it will not start new threads each time you submit a task to it.
I didn't mention shutdown before but you should shutdown the service once you no longer need it to release its resources.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|