How to make a delay in processing project? - java

I'm using Java within a Processing project. I'm trying to make a delay that doesn't stop the program, but stops only a given block of code. That "processing" block of code could for example add 1 to a variable, then wait one second and then add 1 again. The problem is that delay() (see reference) stops the whole program and Thread.sleep() doesn't work in a Processing project.

You should not use delay() or Thread.sleep() in Processing unless you're already using your own threads. Don't use it on the default Processing thread (so don't use it in any of the Processing functions).
Instead, use the frameCount variable or the millis() function to get the time that your event starts, and then check that against the current time to determine when to stop the event.
Here's an example that shows a circle for 5 seconds whenever the user clicks:
int clickTime = 0;
boolean showCircle = false;
void draw(){
background(64);
if(showCircle){
ellipse(width/2, height/2, width, height);
if(clickTime + 5*1000 < millis()){
showCircle = false;
}
}
}
void mousePressed(){
clickTime = millis();
showCircle = true;
}
Side note: please try to use proper punctuation when you type. Right now your question is just one long run-on sentence, which makes it very hard to read.

Related

Java/Processing mousePressed in loop not working

So I was making a simple game in Java + Processing where there were buttons and loops in draw(). Apparently the PApplet function mousePressed() doesn't work constantly if there is a loop, so I tried putting my own checkmouse() function to be checked during the loop. However, it still doesn't work. How do I make it so that I can run a game with while-loops and constantly check for mousePressed at the same time?
//draw() func
public void draw() {
for (int i = 0; i < 10000; i++) { //to simulate a while loop
//do something, like run some other functions that create the buttons
checkmouse();
}
}
//checkmouse function
public void checkmouse() {
if (mousePressed) {
System.out.println("x");
}
}
When I click the mouse in the processing window, it never shows "x" even though checkmouse() runs every time it loops, so theoretically it should be checking it pretty constantly while the loop runs.
Also could someone explain why this doesn't work?
boolean esc = false;
while (!esc) {
if (mousePressed) {
System.out.println("x");
esc = true;
}
}
The event variables (mousePressed, keyPressed, etc.) are updated between calls to the draw() function.
In other words: the mousePressed function will never change within a call to the draw() function. You need to let the draw() function complete and then be called again if you want the event variables to be updated.
Behind the scenes, this is because Processing is single-threaded. (This is by design, because multi-threaded UI programs are a nightmare.)
Taking a step back, you probably don't want to include a long loop inside your draw() function. Take advantage of the 60 FPS loop that's implemented by Processing instead.

java: make program wait until transition is finished

I've been writing a method to switch two images. This method is called in a mouse drag-and-drop event and is followed by another method that lets images drop down a few positions (I'm talking about a sort of candy crush mechanism).
In my case, the transition in the second method starts before the switch is done, which is why you can barely see the switch.
What I'm looking for is a way to make the program wait until the first transition is finished before it steps into the next method. Thread.sleep() isn't working for me since it stops the switch animation as well, and I don't know how to use the transition.setOnFinished() properly within my switch method without causing an infinite loop.
This is part of my switch method:
public void animateSwitch(int xFirst, int yFirst, int xLast, int yLast) {
/.../
ParallelTransition allMovements = new ParallelTransition();
TranslateTransition tt = new TranslateTransition(Duration.millis(FALL_TIME_PER_ROW), getNodeFromGridPane(grdPane, xFirst, yFirst));
TranslateTransition tt2 = new TranslateTransition(Duration.millis(FALL_TIME_PER_ROW), getNodeFromGridPane(grdPane, xLast, yLast));
Image old = iv1.getImage();
iv1.setImage(iv2.getImage());
iv1.setTranslateX(iv2.getX());
iv1.setTranslateY(iv2.getY());
iv2.setImage(old);
iv2.setTranslateX(iv1.getX());
iv2.setTranslateY(iv1.getY());
if (xFirst == xLast) {
tt.toYProperty().set(0);
tt.toXProperty().set(tt.getFromX());
if (yFirst < yLast) {
tt.fromYProperty().set(rowHeight);
tt2.fromYProperty().set(-rowHeight);
}
else {
tt.fromYProperty().set(-rowHeight);
tt2.fromYProperty().set(rowHeight);
}
tt2.toYProperty().set(0);
tt2.toXProperty().set(tt2.getFromX());
}
else if (yFirst == yLast) {
tt.toXProperty().set(0);
tt.toYProperty().set(tt.getFromY());
if (xFirst < xLast) {
tt.fromXProperty().set(rowWidth);
tt2.fromXProperty().set(-rowWidth);
}
else {
tt.fromXProperty().set(-rowWidth);
tt2.fromXProperty().set(rowWidth);
}
tt2.toXProperty().set(0);
tt2.toYProperty().set(tt2.getFromY());
}
allMovements.getChildren().add(tt);
allMovements.getChildren().add(tt2);
allMovements.play();
}
Thanks in advance!
You will have to set the onFinished event handler using allMovements.setOnFinished(eventHandler); Here eventHandler is an object that implements the EventHandler interface.
EDIT:
I skipped past the part where you don't know how to prevent an infinite loop using this solution. You can use two different eventHandlers to do the different parts. The first calls the second when it finishes. The second doesn't need to call the first, so you will not get into a loop.

Pressing a JButton by hand yields different results to doClick()?

I have a problem when a JButton on my interface, when pressed the button triggers this event listener:
if (event.getSource() == goButton)
{
MainLauncher.doProgram(assetsField.getText(), FileFinder.completePath(String.format("%s\\%s", modDirectoryPath, modList.getSelectedValue())), databaseField.getText());
}
which runs the following code:
public static void doProgram(final String baseGamePath, final String modPath, final String databasePath)
{
new Thread()
{
public void run()
{
System.out.println("Running: " + modPath + "\n");
reader = new MetaDataReader(databasePath);
reader.formConnection();
long start = System.currentTimeMillis();
long temp;
File cache = new File("RegisterCache.SC");
if (!cache.exists())
{
temp = System.currentTimeMillis();
start += System.currentTimeMillis() - temp;
System.out.println("Calculating number of files");
FileFinder baseGame = new FileFinder();
baseGame.calculateNumFiles(baseGamePath);
System.out.println(String.format("Loading %s base game files", baseGame.getNumFiles()));
gui.doProgressBar();
baseGame.findFiles(baseGamePath, true);
gui.killProgressBar();
System.out.println();
//load the base game assets, we want to move this to metadata later
System.out.println("Checking for base game reference errors");
new ReferenceDetector(Table.getRegister()).findReferences(true);
Table.serializeTable(cache); //write the database to cache, we can use it next time
}
else
{
System.out.println("Loading cache");
Table.unserializeTable(cache);
}
gui.doCommands(); //calls reset()!!! be careful with the temporary excludes!
System.out.println("Eliminating base game requires errors");
RequiresWhere.executeRequires(true);
temp = System.currentTimeMillis();
start += System.currentTimeMillis() - temp;
System.out.println("Calculating number of files");
FileFinder mod = new FileFinder();
mod.calculateNumFiles(modPath);
System.out.println(String.format("Loading %s mod files", mod.getNumFiles()));
gui.doProgressBar();
mod.findFiles(modPath, false);
gui.killProgressBar();
System.out.println();
System.out.println("Finding reference errors");
new ReferenceDetector(Table.getRegister()).findReferences(false);
System.out.println("Finding requires errors");
RequiresWhere.executeRequires(false);
System.out.println("Checks complete");
reader.killConnection();
System.out.println(String.format("Execution Time: %dms", System.currentTimeMillis() - start));
Table.reset();
}
}.run();
}
The odd thing is this:
When testing I didn't have my button added to the interface, and so on main() I was calling goButton.doClick(); which triggered the doProgram(), and gives me the results I expected which is this:
a couple of things are printed out (to a JTextArea on the interface that receives from System.out.println()), a progress bar pops up above the console, and goes from 0% to 100% in around 10 seconds, disappears, a few more things are printed etc etc.
However when I added the button to the interface I clicked it and the behavior was not the same at all:
Nothing is printed. The progress Bar comes up, and stays at 0% for 10 seconds, then disappears, a few seconds later the doProgram finishes executing and all the information that should have been printed during runtime is suddenly printed all at once.
Can anybody tell me what is causing this strange behavior and how it can be fixed?
I would post a SSCCE, but it is a little difficult to do for this program as there are so many tasks and subprocesses. Note that, the progress bar I use it run on the GUI thread, the main code is done in it's own thread (as you can see)
EDIT: I added setEnabled(false); and true inside the listener surrounding the call to doProgram, and when the button is programatically pressed, the button is greyed out and this renabled as I expect, however if I click the button by hand it does not disable, and I can press it again
The code looks a bit confusing.
However, first of all: You are calling the run() method of the new Thread that you are creating there. This will cause the code from the run() method to be executed by the thread that calls doProgram, and not by the new Thread that you are creating there. In order to execute the code really in this new Thread, you have to call start() instead of run().
This explains probably most of the differences that you described. However, keep in mind that modifications to Swing components always have to be done on the Event Dispatch Thread. So whatever you are doing, for example, with gui.doCommands(), make sure that you don't violate this Single Thread Rule.

Java Timer Speeds Up Every Execution

Every time my timer is run, the code executed inside the timer is run faster. Why is this happening?
This code essentially moves a label (holding an image) across the frame.
Every run, the images moves faster.
if (Player.direction == "west") {
timerWest.start();
isCasting = true;
new Magic("westmagic.gif");
timerWest.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int x = Frame.fireMagicLabel.getX();
int y = Frame.fireMagicLabel.getY();
Frame.fireMagicLabel.setLocation(x - 1, y);
LiveUpdating.updateSpell();
CheckHits.spellHit();
Frame.frame.repaint();
if (Frame.fireMagicLabel.getX() <= tempWest) {
timerWest.stop();
new Magic("");
Frame.frame.repaint();
Frame.fireMagicLabel.setLocation(
Frame.redHealthLabel.getX(),
Frame.redHealthLabel.getX());
isCasting = false;
}
}
});
Frame.frame.repaint();
}
On first run, the timer performs x speed. Then the the next run it performs faster, and faster, and faster.
i think you should add the action listener only once.
Ther actionlistener is only needed to be added once.
Also if this does not fix it, somewhere inside the code you haven't posted you apply the speed, this might not be reset and be added on it, which makes it double speed.

Nesting of timers

This post is related to my last post.The block of code changes the text to desired color after desired time.
however, now I want to change the color of a perticular word such that each letter gets the equal time.EG if "hello" have been given a time of 1000 milliseconds (have 5 letters) then 'h''e''l''l''o' each letter should get 1000/5 milliseconds i.e 200 milliseconds each.
I implemented swing timer for this :
public Reminder() {
a[0]=2000;
a[1]=1000;
a[2]=3000;
a[3]=5000;
a[4]=3000;
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
point =point +arr[i].length();
i++;
doc.setCharacterAttributes(0,point+1, textpane.getStyle("Red"), true);
timer.setDelay(a[i]);
}
};
timer = new Timer(a[i], actionListener);
timer.setInitialDelay(0);
timer.start();
For this to happen, shoud I use another Timer inside the actionListener to give further timings to a perticular letter?Or should I first break the time by .length()
and then use the timer?I cannot decide a better way.Any ideas?
You should never need more than one timer. Since you know ahead of time exactly when everything should happen, just calculate those times, put them in a list (sorted by time) and execute each one.
public colorize(int offset, int length) {
long triggerTime[] = new long[length];
long startTime = System.currentTimeMillis();
for (int i=0; i<length; i++) {
triggerTime[i] = startTime + (1000*i)/length;
}
for (int i=0; i<length; i++) {
//just wait for the next time to occur
Thread.sleep(triggerTime[i]-System.currentTimeMillis());
doc.setCharacterAttributes(offset, i+1, textpane.getStyle("Red"), true);
}
}
This may strike you as very pedestrian because it does not use a TimerTask object, but it is effective, efficient, and easy to debug. You simplty call this method on whatever thread you want, and it occupies the entire thread, and the word will be colorized at a rate such it is completed in 1 second.
You could, if you don't have a thread handy, make a timer that calls this, but the only reason for that is to access a thread. The real point is: don't set up multiple timers, just make an array of time values. After one event is satisfied, set to delay until the next time. You never need multiple timers.
It would be a little cleaner if you made an object that represented the coloring of a character (or whatever action you want) and you put together a collection of these actions. Then sort the entire collection by time they are to go off. The loop above would walk through the collection, waiting until the time for the action arrives, and then executing it. Another advantage of this approach is that you could clear the collection and that would terminate the loop.
See the discussion of the overuse of timers on my website to understand why this is bad.

Categories

Resources