I have a problem with a function I have made for a Whack a mole game in java fx.
In the function, I am trying to change the image of 1 to 3 buttons. The problem is that I am trying to set a delay between each image change. I tryed the Wait() function but it gives me a java.lang.IllegalMonitorStateExceptionstrong Exception
The function ChangeImageActive changes the image of a button to tell to the player that he needs to hit the button.
public void ActivateRandomButtons(ArrayList<MSButtons> btnList)
{
try
{
int n;
int numberOfButtons = rand.nextInt(3);
for (int i = 0; i < numberOfButtons; i++)
{
n = rand.nextInt(9);
btnList.get(n).ChangeImageActive();
// Wait 1 second before resuming for loop
wait(1000);
}
}
catch (java.lang.Exception e)
{
System.out.print(e.getMessage().toString());
}
}
I can show more of my code if needed.
Thanks
Related
this is my first question here so I apologize in advance for any question format mistakes. I am trying to make a sound quiz with the sounds of a game. The idea is for the user to click on the button (round speaker icon) and play the sound. Then, choose one of the four images that correspond to the icon of that sound. App layout On every click on one of the ImageViews all four ImageViews should change the resources. However, when I click on any of those ImageViews the app becomes really slow and I get the dialog asking me to wait for it to respond or click OK to close it.
The CPU monitor shows really high percentage at that moment. memory and CPU usage monitor But, I do not get any Memory Out of Bounds Exception.
This is the code of my Array and ArrayLists
int chosenSound;
int locationOfCorrectAnswer = 0;
Integer[] answers = new Integer[4];
ArrayList<Integer> sounds = new ArrayList<Integer>(Arrays.<Integer>asList(R.raw.dismember, R.raw.duel, R.raw.glimpse, R.raw.reapers_scythe, R.raw.vacuum));
ArrayList<Integer> icons = new ArrayList<Integer>(Arrays.<Integer>asList(R.drawable.dismember, R.drawable.duel, R.drawable.glimpse, R.drawable.reapers_schyte, R.drawable.vacuum));
And this is the method for generating new question:
public void generateQuestion() {
Random random = new Random();
chosenSound = random.nextInt(sounds.size());
if (alreadyUsedSounds.size() == icons.size()) {
Toast.makeText(getApplicationContext(), "You used all the sounds!!!", Toast.LENGTH_SHORT).show();
return;
} else {
while (alreadyUsedSounds.contains(icons.get(chosenSound))) {
chosenSound = random.nextInt(sounds.size());
}
}
locationOfCorrectAnswer = random.nextInt(4);
int incorrectAnswerLocation;
for (int i = 0; i < 4; i++) {
if (i == locationOfCorrectAnswer) {
answers[i] = icons.get(chosenSound);
} else {
incorrectAnswerLocation = random.nextInt(sounds.size());
while (incorrectAnswerLocation == chosenSound || Arrays.asList(answers).contains(icons.get(incorrectAnswerLocation))) {
incorrectAnswerLocation = random.nextInt(sounds.size());
}
answers[i] = icons.get(incorrectAnswerLocation);
}
}
button0.setImageResource(answers[0]);
button1.setImageResource(answers[1]);
button2.setImageResource(answers[2]);
button3.setImageResource(answers[3]);
}
Now, I am not sure how to set those ImageView resources without the app crashing. I guess there is a pretty much straightforward way to do this, but being a beginner I would really appreciate any help. Thank you in advance.
I'm making a game for practice and when I hit enter a knife pops up and I want it to look like its flying through air. Right now each time I click enter it skips about an inch and stops.
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "onEnter");
am.put("onEnter", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// Enter pressed
throwKnife = true;
if(move)
{
for(int i = 0; i < 10; i++)
{
try
{
Thread.sleep(10);
knifeX += i;
repaint();
} catch (InterruptedException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
if(knifeX > 1200)
{
throwKnife = false;
move = false;
knifeX = imageX+100;
knifeY = imageY+75;
}
}
throwKnife = true;
}
});
This is paired with the following code in my paint component method
if(throwKnife)
{
g.drawImage(knife, knifeX, knifeY, this);
repaint();
move = true;
}
Based on the use of the key bindings API and repaint, I'm guessing you're using Swing, in which case you're blocking the event dispatching thread with the Thread.sleep
See Concurrency in Swing for the reason why
Have a look at How to use Swing Timers for a simple solution
I should also point out that the ActionListener will be called repeatedly while the key is held down. A better solution would be to use a flag to indicate when the key is "active" and a "main loop" (like a Swing Timer) to update the state accordingly
Of course, this will require you to detect when the key is released, which can be achieved by binding the key again, but for release. See KeyStroke.getKeyStroke(int, int, boolean) for more details
For example, maybe have a look at
smooth animation in java for fast moving objects
How to make this java animation smooth?
How can I make a Java Swing animation smoother
How to make line animation smoother?
Smooth out Java paint animations
How do I make smoother movement?
Right now each time I click enter it skips about an inch and stops.
I believe that in the part you wrote if(move){...} you actually wanted while(move){...}.
With the while clause you can have it move until it satisfies certain condition (like knifeX > 1200).
So, your code should look like this:
while(move)
{
for(int i = 0; i < 10; i++)
{
try
{
Thread.sleep(10);
knifeX += i;
repaint();
} catch (InterruptedException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
if(knifeX > 1200)
{
throwKnife = false;
move = false;
knifeX = imageX+100;
knifeY = imageY+75;
}
}
Hope it helps.
i have a button in java that calls a function when clicked and that function works just fine but the for loop won't refresh the text area. Instead at the end of the function (after 10s) it only shows i = 10 in the text area. I just simply want the text area to refresh and show i at every second and replace the i. I do not want to show them all at once, just replace them;
int i;
for (i = 0; i<4; i++)
{
try
{
input.setText("i = " + i);
Thread.sleep(1000); // delay of 1.000 seconds
}
catch(InterruptedException e)
{
}
}
Assuming you're using Swing, you could attempt using append instead, since I know that works with adding to the textarea:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
input.append("i = " + i + "\n");
}
});
As Maroun suggested, use Timer after this to pace your appending.
I'm wondering why still I couldn't to figure out a way to do this. Although it seems like very simple, I spent my entire day for this. But couldn't do that.
I have set of dice images. 1.png,2.png,.... and 6.png.
There is an ImageView in my layout. That is,
ImageView dice = (ImageView) findViewById(R.id.imageViewrollingdiceOne);
Here I want to change this imageView rapidly to see a some kind of a visual/animation using above 6 images. For that I wrote following piece of code.
Code 1:
for (int j=0;j<10;j++){
int randomNum = random.nextInt(6);
System.out.println("Random Value " + randomNum);
dice.setImageResource(images[randomNum]);
}
Output:
There is not a visual. imageView remains unchanged and suddenly changes at the loop last iteration.
I thought that it is because the loop is executing very fast.
Then I did the following.
Code 2:
for (int j=0;j<10;j++){
int randomNum = random.nextInt(6);
System.out.println("Random Value " + randomNum);
dice.setImageResource(images[randomNum]);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Output:
Again there is not a visual. imageView remains unchanged and suddenly changes at the loop last iteration.
Then I did the following.
Code 3:
final Handler localHandler = new Handler();
Runnable runnableObject = new Runnable() {
public void run() {
final ImageView dice = (ImageView) findViewById(R.id.imageViewrollingdiceOne);
int randomNum = random.nextInt(6);
System.out.println("Random Value" + randomNum);
dice.setImageResource(images[randomNum]);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
for (int j=0;j<10;j++){
localHandler.postDelayed(runnableObject, 1000);
}
Again there is not a visual. imageView remains unchanged and suddenly changes at the loop last iteration. There are no any errors in logcat in all three cases.
I found that threading also doesn't do the trick.
First of all there is already an animation set in android that can help you achive what you are after it is called FrameAnimation, here is an example on how to use it:
FrameAnimation Example
Your First, second and third code are running in the main thread, you should never use sleep in the main thread !.
If you still want to set the image resource manually you can use this code:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
int randomNum = random.nextInt(6);
dice.setImageResource(images[randomNum]);
handler.postDelayed(this, 500);
}
}, 500);
This is helpful when you're using list of items and changing according time interval one by one. Initially i value should be 0, size of list depends.
final Handler handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
if(i<4) {
galleryImg.setImageResource(myImageList[i]);
i++;
} else {
i=0;
}
handler.postDelayed(this, 10000);
}
}, 500);
The reason you're probably not seeing changes is because the final callback to the main UI thread happens after your thread finishes its execution and you only see the final result. Now, this is my (probably poor) understanding and someone more versed in it can probably correct me.
That said you should probably look to using an AnimationDrawable object:
ImageView sImage = (ImageView)findViewById(R.id.imageViewrollingdiceOne);
AnimationDrawable anim = new AnimationDrawable();
for (int j=0;j<6;j++) {
anim.addFrame(new BitmapDrawable(images[j], 200);
}
sImage.setBackgroundDrawable(anim);
anim.setOneShot(false);
anim.start();
This assumes you've generated images[] with the images in random order already. If you want to change that up put whatever code you need in the for-loop.
What it does is creates an animation object much like how you'd see a gif work with a set delay interval between changes (in this code its 200ms). You can elect to change that number if you wish. The setOneShot call makes sure it loops instead of finishing the animation and stopping on the last image.
I am making a Conway's Game of Life program in java, and am trying to change it from the command line version to a GUI. From the command line I just printed an array which showed the generations (the objects such as blocks and blinkers are shown as a series of 1's and 0's where it is blank, and in the GUI I'm showing it as squares (white squares as blank and blue squares where it isn't). But where I'm getting stuck is when I make another method (which replaces the method which prints the array) which checks the grid array, if there is a zero then the square changes from white to blue, and vice-versa. The Conway's Life rules are dealt with in a separate class which is independent, and all this method does is after the rules have changed the array this method checks it.
The rules are done in methods in one class and the GUI components are done in another. But since I need instance of both how would I go about doing it?, merge the two classes (all the GUI classes into the Life one, embed them some how, I am completely stuck on what to do
public void runGUI() {
int x = getX(), y = getY();
x /= squareSize;
y /= squareSize;
for (int i = 0; i < LifeData.grid.length; i++) {
for (int j = 0; j < LifeData.grid[i].length; j++) {
if (LifeData.grid[i][j] == 0)
l.setCell(x, y, l.getCell(x, y) + 1);
else
l.setCell(x, y, l.getCell(x, y) - 1);
this.repaint();
}
}
}
That is what I have changed it to now but when compiling it is saying "non-static variable grid cannot be referenced from a static context" and "non-static method runGUI() cannot be referenced from a static context". When trying to run the method.
Make a separate thread that will execute the game of life and update the GUI.
Something like this
public class GameExecutor implements Runnable {
private static final int DELAY = 1000;
private GameOfLife game;
private boolean stop = false;
private Gui gui;
public GameExecutor(Gui gui, GameOfLife game) {
this.gui = gui;
this.game = game;
};
public void run(){
game.start();
while (!stop) {
game.step(); //execute a step
gui.update(game.getState());
try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {}
}
}
}
Launch this in a thread at startup and pass it your gui. Don't forget to update the gui in the correct Swing thread.
Obviously you'll need to add some code to stop it, too :)