I'm trying to make this GUI where there are these words that fall from the top of the screen and I have the following code in my constructor, where the word moves by one unit every 100 milliseconds. However, when I run the program the word appears at 400 once I start and not at the top of the screen. I suppose that there is a specific method that could update my y value in continuous time? Thanks!
while(y <= 400){
y++;
repaint();
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(Painting.class.getName()).log(Level.SEVERE, null, ex);
}
}
sleeping your thread isn't the best practice to take the desired result, use Timer instead:
Timer timer = new Timer(100, new ActionListener() { //100 is the delay time between each interval
#Override
public void actionPerformed(ActionEvent e) {
repaint();
y ++;
if (y > 400) {
((Timer) e.getSource()).stop();
}
}
});
timer.start();
Related
I have a program that displays a picture of a coin. When the user clicks the coin the coin changes from heads to tails and vice versa. That works fine.
The problem arises when I want to have a button that flips the coin a random number of times (In this case between 3 and 10 times inclusive).
The method used to change the image icon:
flip.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e1) {
playerCoinState = coinState;
System.out.println("Clicked");
int flips = (new Random().nextInt(8)) + 3;
for(int i = 0; i < flips; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException e2){
System.exit(1);
}
System.out.println("Auto Flipped");
changeFace();
}
}
});
And this is the method used to change the ImageIcon of the JLabel coin:
private void changeFace(){
System.out.println("Changing...");
switch(coinState){
case 0:
System.out.println("Coin State 0");
try {
coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Heads.png"))));
} catch (IOException e) {
e.printStackTrace();
}
coinState = 1;
break;
case 1:
System.out.println("Coin State 1");
try {
coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Tails.png"))));
} catch (IOException e) {
e.printStackTrace();
}
coinState = 0;
break;
}
}
The JLabel coin is initialised as:
coin = new JLabel(new ImageIcon("res/Tails.png"));
coinState represents the value of the coin. 0 for heads, 1 for tails.
playerCoinState is used to keep track of the coin state the player has selected before the coin is to be flipped by the computer the random amount of times.
This...
for(int i = 0; i < flips; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException e2){
System.exit(1);
}
System.out.println("Auto Flipped");
changeFace();
}
Is blocking the event dispatching thread, preventing ui from been updated until after the method exits
You should try using a Swing Timer instead, which acts as a pseudo loop, but waits in the background for a prescribed period of time before triggering a tick within the context of the EDT, making it safe to update the UI from
coin = new JLabel(new ImageIcon((ImageIO.read(new File("path"))));
Use this instead of coin.setIcon(new ImageIcon(ImageIO.read(new File("res/Tails.png")))); So you are creating the coin label new every time. If you are working with eclispe and windowbuilder, you can just use the tools on the sidebar.
MadProgrammer helped me to solve this.
The new and improved ActionListener for the button is:
flip.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e1) {
playerCoinState = coinState;
int flips = (new Random().nextInt(10) + 5);
Timer timer = new Timer(400, new ActionListener(){
int counter = 0;
#Override
public void actionPerformed(ActionEvent e) {
if(counter == flips){
((Timer)e.getSource()).stop();
}
changeFace();
counter++;
}
});
timer.start();
}
});
Thanks again MadProgrammer =)
I am just a beginner in Java. We have a college project and we are making a game called othello (also called reversi), we are using Java applet for the game. Board design and gameplay is complete and is working fine but we are having an issue with the timer.
The problem is player's move is not detected until timer has elapsed completely, i.e suppose timer for each move is 10 sec and if the user places his move at the 5th sec, his move will be detected only after 10 sec This behavior does not serve any purpose.
The method I am following is:
Display the time(integer) on the applet screen
Sleep for one sec
Increment time and update graphics
The whole thing is put inside the loop which is actually creating the problem. I need a better and in fact a working modification to this code.
Here are the code of two relevant functions
void startTimer() {
Graphics g = getGraphics();
for(sec =0 ; sec < 10 ; sec++){
String time = new String();
time = Integer.toString(sec);
g.drawString(time, WIDTH+80, 145);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(NewApplet.class.getName()).log(Level.SEVERE, null, ex);
}
update(getGraphics());
}
}
public boolean mouseUp(Event e, int x, int y) {
int column = (int)(x / (WIDTH / 8));
int row = (int)(y / (WIDTH / 8));
if (turn == BLACK) {
if (placeLegalCheck(column, row, turn) == true){
flipDisk(column, row, turn);
turn = - turn;
diskCount();
startTimer();
update(getGraphics());
try {
Thread.sleep(500);
} catch (Exception excep){
}
}
}
if (turn == WHITE) {
if (placeLegalCheck(column, row, turn) == true){
flipDisk(column, row, turn);
turn = - turn;
diskCount();
startTimer();
update(getGraphics());
try {
Thread.sleep(500);
} catch (Exception excep){
}
}
}
return true;
}
In a game board we are developing in Java we want to show a sort of rolling dice when a button is pressed. We are trying to use the following image as a sprite:
so when the button is pressed, here's what happens:
private void startAnimationDie(final JPanel panel) {
int launchResult = /* getting a launch dice result from the core game (from 1 to 6)*/
new Thread() {
public void run() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
BufferedImage[] animationBuffer = initAnimationBuffer();
BufferedImage[][] exactDieFaces = initExactDieFaces();
int launchResult = coreGame.launchDie();
coreGame.getMyPartecipant().setLastLaunch(launchResult);
AnimationSprite animation = new AnimationSprite(animationBuffer, Constants.DIE_ANIMATION_SPEED);
animation.start();
JLabel resultDie = new JLabel();
resultDie.setBounds(60, 265, Constants.DIE_SIZE, Constants.DIE_SIZE);
for (int counter = 0; counter < Constants.DIE_ANIMATION_SPEED * 100; counter++) {
animation.update();
//panel.removeAll();
panel.updateUI();
//System.out.println("infor");
resultDie.setIcon(new ImageIcon(animationBuffer[counter % Constants.ROTATIONS]));
panel.add(resultDie);
panel.updateUI();
updateUI();
}
panel.removeAll();
panel.updateUI();
AnimationSprite resultAnimation = new AnimationSprite(exactDieFaces[launchResult - 1], 6);
resultAnimation.start();
resultAnimation.update();
System.out.println("0");
resultDie.setIcon(new ImageIcon(exactDieFaces[launchResult - 1][0]));
System.out.println("1");
resultDie.setBounds(60, 265, Constants.DIE_SIZE, Constants.DIE_SIZE);
System.out.println("2");
panel.add(resultDie);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
userPlayer.getGamePanel().makePossibleMoveFlash();
}
});
} catch (Exception ex) {
}
}
}.start();
where exactDieFaces contains the dice faces according to the pawn color which is launching and that face will be shown after the simulated rolling has finished; on the other hand, animationBuffer contains 40 or 50 random faces of all colors taken from the sprite image like that:
private BufferedImage[] initAnimationBuffer() {
BufferedImage[] result = new BufferedImage[Constants.ROTATIONS];
int rowSprite, colSprite;
Random random = new Random();
for (int i = 0; i < Constants.ROTATIONS; i++) {
rowSprite = 1 + random.nextInt(5);
colSprite = 1 + random.nextInt(5);
result[i] = DieSprite.getSpriteExact(0 /* offset */,colSprite, rowSprite);
}
return result;
}
The problem is that nothing is shown during the animation: I expected to see many dice faces change one after the other until the for cycle ends but nothing is shown...The only thing I see is the launch result according to the color pawn which has launched the die but meanwhile there is nothing...can you help me?
If I understand your code correctly you are attempting to update the UI many times within the same for loop. That's not how animation works. You need a timer which regularly notifies you to move to the next frame to view.
A good place to start in understanding how to use timers is here in the Java tutorial.
Ok so I have created a game and it works perfectly, except I don't want the player to win after just one defeat I want him to have to kill 10 enemies well I created my spawnmore method and I know the problem I just don't know how to fix it, in my if statement I have it saying if(dead < 10) then do my stuff, when I only want it to do it once every time dead increments one if you get what I mean here's my method thanks
public void spawnMore(){
int delay = 1000;
Timer time = new Timer(delay, new ActionListener(){
public void actionPerformed(ActionEvent e){
if(WizardCells[BadGuy.getx()][BadGuy.gety()].getIcon() != null){
return;
}
if(WizardCells[BadGuy.getx()][BadGuy.gety()].getIcon() == null){
dead += 1;
}
if(dead < 10){
int where = (int)(10 + Math.random() *9);
BadGuy.spawnEnemy(where, where);
move();
}
}
});
time.start();
}
If I understand you correctly, you could just move the if statement inside the previous if statement:
public void spawnMore(){
int delay = 1000;
Timer time = new Timer(delay, new ActionListener(){
public void actionPerformed(ActionEvent e){
if(WizardCells[BadGuy.getx()][BadGuy.gety()].getIcon() != null){
return;
}
if(WizardCells[BadGuy.getx()][BadGuy.gety()].getIcon() == null){
dead += 1;
if(dead < 10){
int where = (int)(10 + Math.random() *9);
BadGuy.spawnEnemy(where, where);
move();
}
}
}
});
time.start();
}
I am working on an app that counts the number of questions marks in a few paragraphs of text.
After the scanning is done (which takes no time at all) I would love to have the total presented after the number goes from 0 to TOTAL. So, for 10: 0,1,2,3,4,5,6,7,8,9 10 and then STOP.
I have tried a couple of different techniques:
TextView sentScore = (TextView) findViewById(R.id.sentScore);
long freezeTime = SystemClock.uptimeMillis();
for (int i = 0; i < sent; i++) {
if ((SystemClock.uptimeMillis() - freezeTime) > 500) {
sentScore.setText(sent.toString());
}
}
Also I tried this:
for (int i = 0; i < sent; i++) {
// try {
Thread.sleep(500);
} catch (InterruptedException ie) {
sentScore.setText(i.toString());
}
}
I am sure these are both completely amateur attempts. Any help would be much-appreciated.
Thanks,
Richard
I've used a more conventional Android-style animation for this:
ValueAnimator animator = new ValueAnimator();
animator.setObjectValues(0, count);
animator.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
view.setText(String.valueOf(animation.getAnimatedValue()));
}
});
animator.setEvaluator(new TypeEvaluator<Integer>() {
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
return Math.round(startValue + (endValue - startValue) * fraction);
}
});
animator.setDuration(1000);
animator.start();
You can play with the 0 and count values to make the counter go from any number to any number, and play with the 1000 to set the duration of the entire animation.
Note that this supports Android API level 11 and above, but you can use the awesome nineoldandroids project to make it backward compatible easily.
Try this:
private int counter = 0;
private int total = 30; // the total number
//...
//when you want to start the counting start the thread bellow.
new Thread(new Runnable() {
public void run() {
while (counter < total) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t.post(new Runnable() {
public void run() {
t.setText("" + counter);
}
});
counter++;
}
}
}).start();
The question is very old, but I am posting this so that it would help someone else.
I have used these 2 amazing libraries.
Try them
https://github.com/MasayukiSuda/CountAnimationTextView
Or
2. https://github.com/robinhood/ticker
Hope this helps :) Happy Coding!!!
Use TextSitcher
for the best effects. It will transform the text softly.
When coming to the change of the text use the below Code.
> int number = 0;
> Timer obj = new Timer();
> TimerTask tt = new TimerTask() {
> #Override public void run() {
> // TODO Auto-generated method stub
> textView.setText(number++);
> if(number < score)
> obj.schedule(tt, 200); } };
> obj.schedule(tt, 200);
Use a worker thread to do the waiting and update your UI thread.
You could use an AsyncTask, though it might be an overkill for this job. If you use this, In the doInBackground() loop over the number of sleep periods and after every sleep period, update the count in the UIthread.
There you go! Slukain just gave you the working code :P
Maybe try changing the for loop to something like:
int count = 0;
while (count != sent) {
if ((SystemClock.uptimeMillis() - freezeTime) > 500) {
count++;
sentScore.setText("" + count);
freezeTime = SystemClock.uptimeMillis();
}
}