Stepping through an algorithm - can't do it in java?
I'm trying to solve a tiling problem displayed in a GUI. The problem is, I need the algorithm to solve the problem step by step. But whenever I click start, it just solves it. Here's my code.
if (e.getSource() == start){//push the start button
while (!isSolved(boxes)){//until the puzzle is solved
if (condition){
right.doClick();//click on the rightButton
}
else{
left.doClick();//click on the leftButton
}
try{ /sleepfor 1000 seconds so i can see the move
Thread.sleep(1000);
}catch (InterruptedException e1){
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
What's wrong? I make it sleep after every iteration of the while loop but instead it doesnt show the intermediate steps. It does wait the 1 second after every iteration, but none of the steps are shown on the gui - the buttons don't appear to get pushed every second. It should show the steps every second, right?
Please help
Thanks in advance.
jboolean23
You are making the Event Dispatching Thread sleep. Do this on another thread.
I'm not sure how to do it on another thread. Could you please explain?
> I'm not sure how to do it on another thread. Could> you please explain?This goes into a good bit of detail. It should help. http://java.sun.com/docs/books/tutorial/uiswing/concurrency/index.html
> I'm not sure how to do it on another thread. Could
> you please explain?
Swing runs a special Thread called the dispatcher thread, which does all the GUI management stuff, redraws and so on.
When it calls back to your actionPerformed method or whatever the callback is on that thread. The important thing is that nothing in the way of screen updates can happen untill that call returns. So your actionPerformed should return withing a fraction of a second (the only common exception is when it calls a model dialog).
In a case like this what it needs to to is to build and start a new thread to do the long-running process, and then return, leaving the child thread doing its stuff.
To start a thread create a class which implements Runnable. Usually an anonymous class will to the job. Then you pass an object of this class to the constructor of a new Thread. Call start() and the Thread is up and running.
However, when such a thread requires changes to be made in what's on display the updates need to be done back on the dispatcher thread. What it does is to create another Runnable class and put it on the dispatcher thread's TODO list.
Learn to use small, often anonymous classes for these purposes. And that goes for ActionListener classes too - don't make your JFrame or whatever the ActionListner.
In a case like this you should probably also disable the control that starts the model while the model is running.
Starting a thread using an anonymous class would look something like this:
modelThread = new Thread(new Runnable() { // anonymous class syntax
public void run() { // this is the code that's run as the thread's body
doThreadStuff(); // a private method of the outer class
}
},// end of anonymous class definition
"Model Thread"); // give the thread a name - it helps with debugging
modelThread.start();
To do screen updates from a background thread like this use EventQueue.invokeLater()
I'm sorry. I'm really not that comfortable with EventQueue.invokeLater() even though I've read about invokeLater(). Would you please explain how exactly to use it in this example? Thanks for your help so far, guys.
> okIs this an ok I am waiting or ok I got it fixed?
try { //sleep for 1000 seconds so i can see the move
Thread.sleep(1000);
} catch (InterruptedException e1) {
BTW: Your assumption (in your comment) is incorrect - you're not sleeping for 1000 seconds, only 1 second.
The parameter is milliseconds, not seconds.
> It does wait the 1 second after every iteration,Sorry, missed that the 1st time. Ignore my previous post.
> I'm sorry. I'm really not that comfortable with
> EventQueue.invokeLater() even though I've read about
> invokeLater(). Would you please explain how exactly
> to use it in this example?
It's pretty much the same as starting a thread. You create a Runnable object and pass it to invokeLater. That puts it on swing's TODO list and, at some point in the not too distant future, the run method gets called by the dispatcher thread.
As with threads, more often than not, you use an anoymous class as the Runnable.