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.
Related
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
I'm making some simple animation using Actors (Labels, to be precize) and Actions.
My initial plan was to move one of them far to the left instantly, then make it smoothly appear through the edge of screen, replacing another. But every time a new Action is executed, Label's position resets, so I can't get the effect I planned. How do I avoid it?
Here's code, if you need it:
newAttack.addAction(Actions.moveBy(-1 * game.W, 0));
newAttack.setText(game.local.get(_attack));
newAttackType.background = game.skin.getDrawable("attack_" + getAttackType(_attack));
lastAttack.addAction(Actions.sequence(Actions.moveBy(game.W, 0, 1.5f),
Actions.run(new Runnable() {
public void run() {
System.out.println(lastAttack.getX() + " " + lastAttack.getY());
newAttack.addAction(Actions.sequence(Actions.moveBy(game.W, 0, 1.5f), Actions.run(new Runnable() {
public void run() {
lastAttack.addAction(Actions.moveBy(-1 * game.W, 0));
newAttack.addAction(Actions.moveBy(-1 * game.W, 0));
System.out.println(lastAttack.getX() + " " + lastAttack.getY() + "\n" + "--");
lastAttack.setText(game.local.get(_attack));
lastAttackType.background = game.skin.getDrawable("attack_" + getAttackType(_attack));
}
})));
}
})));
This may not work, but looking into the source code of Label.setText() reveals that the method calls Actor.invalidateHierarchy. This means that whatever is containing the lastAttack actor will reset the lastAttack's position.
So since you are adding the actions before you are calling Label.setText(), the position will be reset and then the actions won't work properly.
You should try setting the text, then setting the position of the actor to off screen, and then adding the slide in Action.
So I have been having some trouble trying to create a teletype effect for my swing program. I essentially want to update a JFrame at 40ms increments with a new letter, "typing" out a message to the user. However, it flickers a lot when I try to do this. The method is below:
public static void animateTeletype(String input, JTextArea displayArea)
throws InterruptedException {
displayArea.setText("");
String s = "";
for(int i = 0; i<input.length(); i++) {
s += input.substring(i, i+1);
displayArea.setText(textToDisplay);
Thread.sleep(40);
displayArea.update(displayArea.getGraphics());
}
}
I figure the problem stems from updating the text too fast, and it has to update more than it can handle. I am not sure how I would go about this issue, as reducing tick time will make text scroll too slowly. Any advice is appreciated!
** I've solved the problem. This is my new code:
static Timer timer = null;
public static void animateTeletype(final String input, final JTextArea displayArea) throws InterruptedException
{
final String[] s = new String[1];
s[0] = " ";
final int[] i = new int[1];
i[0] = 0;
displayArea.setText("");
timer = new Timer(30, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
s[0] = input.substring(i[0], i[0]+1);
i[0]++;
displayArea.append(s[0]);
if(displayArea.getText().equals(input))
timer.stop();
}
});
timer.start();
}
displayArea.update(displayArea.getGraphics());
Don't use the update() method. There is never any reason to do that. Get rid of that statement.
Swing components will automatically repaint themselves.
displayArea.setText(textToDisplay);
Don't uset setText(...) to add new text.
Instead you should be using:
displayArea.append( "some more text" );
Don't use Thread.sleep(40) for animation. It you want animation then use a Swing Timer to schedule the animation.
I suggest you look at other section of the tutorial for Swing basics. Maybe something like How to Use Text Fields.
I've created a tool where I paste some data in a text area and this data is being split per lines by (\n) in an array.
My tool works perfect, I just need to connect this progress of the array to the progress bar so the user may know what's going on.
so if the array will have 10 lines the progress bar shall start from one and count till it reaches ten when the tool moves to the next line.
so I mean when it starts working on the array in position 0, the progress bar shall show 1, and when the array moved to position 1, progress bar shall show 2 .......
Here is an example of my code:
// Run button (start the search)
final JButton btn = new JButton("Run");
btn.addActionListener(new ActionListener() {
#SuppressWarnings("resource")
public void actionPerformed(ActionEvent e) {
try {
String getTextArea;
getTextArea = textArea.getText();
// converting the input to an array
String[] arr = getTextArea.split("\\n");
// clearing the text
textArea_1.setText("");
//line = arr.length;
// looping for the input
// doing something.....
}
// end of for loop
} catch (Exception e2) {
JOptionPane.showMessageDialog(null, "Search was not completed due to bad connection, please try pressing run again or close the tool and reopen it");
}
}
});
// Creating the progress bar
JProgressBar progressBar = new JProgressBar();
progressBar.setStringPainted(true);
progressBar.setValue(0);
for(int z = 0; z <= line; z++) {
progressBar.setValue(z);
z = z + 1;
progressBar.repaint();
}
progressBar.setBounds(364, 11, 139, 22);
contentPane.add(progressBar);
Thank you for your help in advance
I've interpreted your question as how do I get the line number to be displayed instead of the percentage?
If that is the question, then you need to use the JProgressBar's setString(String s) method as well as setValue(int n)
For example:
// Set up of the JProgressBar
final int MIN = 0;
final int MAX = 100;
JProgressBar progressBar = new JProgressBar(MIN, MAX);
progressBar.setStringPainted(true); // show the text on the progress bar
progressBar.setString("Loop no. " + MIN); // initial display
// Code to update the JProgressBar
for (int i=MIN; i<=MAX; i++) {
progressBar.setValue(i);
progressBar.setString("Loop no. " + i);
}
Personally I prefer to use an implementation of BoundedRangeModel when working with progress bars. Swing provides DefaultBoundedRangeModel which is good for most tasks.
Remember to use concurrency correctly in your implementation, otherwise your interface will be unrespsonive if the task is long. SwingWorker can assist you with this https://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html
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.