Quirky trouble updating an image for a Jlabel - java

I'm having some trouble with an assignment I'm working on.
Part of it is to "animate" the rolling of a pair of die. I have 6 JPEGS, one of each of the sides. Instead of rolling, I want it to cycle through the images. I'm trying to use setIcon over and over in a loop, and use Thread.sleep() for a delay. This, among other things, all happens when the user hits a button (the event). Instead of displaying the images, it waits the correct amount of time and displays only the last image. Here's the function I'm calling to perform the loop:
private void aniRoll(){
for(int i = 0; i < 10; i++){
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face1.jpg")));
try{
Thread.sleep(1000); // Sleep for 1 sec
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face2.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face3.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face4.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face5.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face6.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
}
}
die1Disp is the name of my JLabel, aniRoll() is the function I'm calling to perform the loop (made private because I don't want anything outside of my GUI class to call it), and the faceX.jpg are my images.
What I can't understand is no matter where I put the Thread.sleep() it delays the program first, and then only displays the last image. For example:
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face1.jpg")));
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face2.jpg")));
//bunch of extra code
try{
Thread.sleep(10000); // Sleep for 10 sec
}
catch(InterruptedException e){}
This will wait for 10 seconds and then display only the second image. It doesn't blip the first quickly, display the second, then wait, it waits and only displays the second image. This quirk really has me baffled, and I'm not sure how to correct it. I'm using NetBeans IDE 7.01 as my editor and for the basic layout and code generation I'm using a Component Palette.
--Thanks

First you must make the changes on the gui thread. See
SwingUtils.invokeLater.
Also Thread.sleep isn't going to cut it, you should be using a javax.swing.Timer to specify when to switch icons.

There's a single UI thread managing events and repainting (updating the screen). You put it to sleep. Doing so means that nothing else was going to happen (in regard to the UI) until it wakes up.
In your actionPerformed method, start a new Thread that will do the repainting. That should fix it.

Related

JProgressBar moves instantly and not gradually (java)

I want to make a ProgressBar move gradually using a Jbutton. To achieve this I am using a for loop and the method Thread.sleep. The problem is that insted of moving a tiny bit every second (the progress bar) after pressing the button, the program waits until the loop finishes and then does instantly move the progress up. When I take the loop outside of the button listener it works as I want but I really need it to work when pressing the button. Here is the code:
progressBar.setOrientation(SwingConstants.VERTICAL);
progressBar.setMinimum(0);
progressBar.setMaximum(100);
progressBar.setValue(50);
panel1.setLayout(null);
panel1.add(progressBar);
progressBar.setBounds(40,6,100,100);
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int counter = 5;
for (int i = 0; i < 5; i++) {
progressBar.setValue(progressBar.getValue() + counter);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
}
});
If anyone can help me I will be very grateful!
Your code runs on the Event Dispatcher Thread (EDT). That thread is responsible for handling events, but also for repainting. Because it's just one thread, the repainting only occurs after your method ends.
There are some ways to solve this. In your case, a javax.swing.Timer would probably be easiest. Instead of running the loop in a single method, the button click starts a timer that runs every second. When it's done the timer can cancel itself. A slightly more difficult alternative is to use a SwingWorker. You could publish data in the doInBackGround method, and override process to perform the updates to the progress bar.
For more information, please read Concurrency in Swing.

Computer Vs Computer Loop Java Applet

I am having issues setting up a computer vs computer loop in my java game applet. I have been trying for 3 days now to effectively add a one second delay between the two computer-player turns, while also repainting the board. I have tried try/catch/thread.sleep and wait and a few other tricks, however none have been successful. In the program's current state, when a computer vs computer game is initiated, the program freezes for the duration of the game (with one second delays between moves) and then displays the final board when the game has finished. How can I make it so the program repaints/delays after each move? From all of the reading I have done, I am aware that the following implementation will not work but my issue is I cannot figure out how to do it any other way.
Thanks in advance!
The following code is inside my actionPerformed listener method
if (event.getSource() == startAIvAI)
{
drawing.clear();
while (drawing.hasWon() == -1 && !drawing.isFull())
{
go1();
repaint();
try {
Thread.sleep(1000);
} catch (Exception e) {}
go2();
repaint();
try {
Thread.sleep(1000);
} catch (Exception e) {}
}
}
When you invoke Thread.sleep(1000); which Thread do you think you're pausing? Probable the one handling event given your code start with if (event.getSource() == startAIvAI).
You should read this to understand what to do: Sleep method locks my GUI

How to freeze my jframe while program flow is happening in java

So I have a little puzzle made in Java, and let's just say there are buttons too on this puzzle which represent the puzzle. There is a solving method where a series of buttons are clicked to find a "solution", and it takes around 1 minute to solve it, so that is 1 minute of just clicking buttons
During this one minute, you notice the buttons being clicked by the computer as it changes color and shape during the program flow, I was wondering if there was a way to freeze the jframe before the solving() method is invoked and then unfreezes into the solution when the method is over?
I am a little confused to exactly what you are asking, but I would suggest using this code to do what I believe you are asking for
private static boolean solveDone = false; //This should go in a the class, not here.
//Create a new thread to handle processes while the JFrame is frozen
SwingUtilities.invokeLater(new Thread(){
public void run(){
//Code to run while the JFrame is frozen should be put here.
main.solveDone = true;
}
});
//Sleep the program until the process is done.
try{
while(!solveDone) {
Thread.sleep(10); //Interval in milliseconds to check if the puzzle is done goes here.
}
solveDone = false;
}catch(InterruptedException e){
e.printStackTrace();
System.exit(-1);
}
//Code to run after solving goes here.
Now, this isn't the cleanest way to do this type of thing, but I believe it should work.
On the other hand, if you know exactly how much time it is going to take, you could do this.
SwingUtilities.invokeLater(new Thread(){
public void run(){
//Code to run while the JFrame is frozen should be put here.
}
});
try{
Thread.sleep(1000); //The time in milliseconds to sleep the JFrame
}catch(InterruptedException e){
e.printStackTrace();
System.exit(-1);
}
//Code to run after solving goes here.

Delay not working properly, but instead does all the action after a big delay

so Im doing a project of a tic tac toe using artificial intelligence, and I wanted to make an option so you could replay the game to see what happend in the last round, My intentions were to make the replay as its actually playing right now, which means after each move will be shown there wil lbe a delay and then the next one will occur.And instead of working as expected the delay jsut goes all at a time without anything happening until suddenyl the whole game just shows up without beinge displayed as a game but as a finishing screen' anyway here is the code:
replayMode=true;
setStatus("Replay Playing...");
ifButtonsEnabled(true);
initBoard();
int turn=0;
Move current;
for(int i=0;i<replayer.getSizeOfVect();i++)
{
current=replayer.getMoveAt(i);
if(i%2==0)
{
buttons[current.getI()][current.getJ()].setText("X");
}
else
{
buttons[current.getI()][current.getJ()].setText("O");
}
try {
Thread.sleep(650);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
setStatus("Replay ended.");
replayMode=false;
Usually when you see this kind of effect in a GUI program, it's because you need to yield control back to the GUI thread's event loop for any drawing to happen. Rather than Thread.sleep I recommend using a timer with a 650ms interval and doing one "step" of the animation with each tick of the timer.

jSlider code causes the application to hang

This jSlider code causes the application to hang.
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
for(int i=0;i<100;i++)
{
jSlider1.setValue(i);
Thread.sleep(3000);
}
} catch (InterruptedException ex) {
Logger.getLogger(AsdView.class.getName()).log(Level.SEVERE, null, ex);
}
}
thank you guys i am updating the answer
Timer time = new Timer(100, new ActionListener() {
int percent = 0;
#Override
public void actionPerformed(ActionEvent e) {
percent++;
if (percent>100)
percent = 0;
jSlider1.setValue((int)(100*(percent/600.0)));
}
});
time.start();
I am guessing you are trying to do some kind of smooth scroll.
That code freezes because the event thread that handles the window painting, sizing, etc..., is being frozen by you executing Thread.sleep(3000), 100 times.
I would recommend that you use a Swing timer that changes the scroll bar little by little.
i don't know why you put the sleep for 3 secs and that too in for loop of 100
3*100 = 5 mins so it will hang upto 5 mins
remove Thread.sleep(3000);
it will work fine and won't hang
When you say your application 'hangs', that generally means that you have some sort of deadlock that prevents your threads from making progress. Is that what you're observing in your program? The way it's currently written, the current thread of execution will take at least 300 seconds to complete. Is this work being done on the main thread of execution? If so, you may want to consider creating a new Thread to do this work.

Categories

Resources