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.
Related
I am making a board game were I have 3 AI players and a user playing. When the user presses a Button to give its turn up to the AI's I want to add a delay so the user can see every move each AI makes.
I have tried a thread sleep and handler but it seems they are unable to update the board and add a delay with each iteration of the while loop. The code without any attempt to add a delay can be found below. I would need to add a delay after the inner while loop terminates.
public void onClickNextTurn(View view){
boolean turnFinished;
findViewById(R.id.btnChangeTurn).setVisibility(View.INVISIBLE);
while (this.playerTurn<4) {
this.playerTurn++;
turnFinished=false;
while (!turnFinished) {
diceRoll();
MoveTriplet result = ai[playerTurn-2].aiTurn(this.boardPieceLocations, this.homeLocations, this.finishLocations, this.roll, playerTurn);
if (result != null) {
if (result.getMoveType() == 'b') { //The Artificial Opponent is moving from one home location to the board AND gets to roll again
this.homeLocations[playerTurn - 1][result.getPreviousIndex()] = 0;
if (this.boardPieceLocations[result.getNextIndex()] != 0)
returnPieceHome(this.boardPieceLocations[result.getNextIndex()]);
this.boardPieceLocations[result.getNextIndex()] = this.playerTurn;
this.homeButtons[playerTurn - 1][result.getPreviousIndex()].setBackgroundColor(getResources().getColor(R.color.colorHoles));
this.buttons[result.getNextIndex()].setBackgroundColor(colors[playerTurn - 1]);
}
So if anyone could point me in the right direction on how I could add an delay between iterations of the outer while loop and at the same time updating the my board. Thanks in advance!
Try looking at the standard Android animation APIs. Those should handle the timing for you and be smoother anyways -- plus, they'll use the GPU more efficiently for you.
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.
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.
I´ve been dealing with this for some days now I´ve serach over the internet and tried everything that came up to my mind but nothing works. My problem is that I am making a pexeso game, we have some additionaly library directly from school or something like that which allows us to draw some pictures instead of comad line only... (We didn´t have graphics yet) So my problem is that my game is running in cycle and waiting for my click som I am checking the condition if click was made. And if I want to click I have to have just a method public void vyberSuradnice(int, int) declared in my code.
So the problem is that my game is runinng in cycle and checking if click was made. But when the click was made the method vyberSuradnice is executed and there I am setting the value off atrrbiute - cakatNaKlik on false, so click was made and one step of game can be made.. But since the function is running in cycle, then even If I clicked and in the method vyberSuradnice the value of attribute is changed, my function which is running in cycle isn´t respond to that change, so the game isn´t going on.
this is the method for clicking
public void vyberSuradnice(int paSuradnicaX, int paSuradnicaY) {
this.riadokOdkry = (paSuradnicaY ) / 25;
this.stlpecOdkry = (paSuradnicaX - 10) / 25;
if (this.riadokOdkry > this.aPocetRiadkov || this.stlpecOdkry > this.aPocetStlpcov) {
System.out.println("Klikli ste mimo hracieho pola ");
} else {
this.cakatNaKlik = false;
}
}
This the part of code where I am waiting for cakatNaklik - false value
while (uhadol) {
if (!this.cakatNaKlik) {
if (this.pocetUhadnutych >= (this.aPocetRiadkov * this.aPocetStlpcov) / 2) {
uhadol = false;
}
this.hraciaPlocha[this.riadokOdkry][this.stlpecOdkry].setUhadnute(true);
But even if the value is changed in method vyberSuradnice this condition is not triggered. But when I make something like this :
while (uhadol) {
System.out.print(this.cakatNaKlik);
if (!this.cakatNaKlik) {
if (this.pocetUhadnutych >= (this.aPocetRiadkov * this.aPocetStlpcov) / 2) {
uhadol = false;
}
this.hraciaPlocha[this.riadokOdkry][this.stlpecOdkry].setUhadnute(true);
the game is working like by writing the variable refresh it or something... but I am getting neverending print of true true or false on command line and this is something I can´t afford to have...
I know this may can be dan by threads but it´s something I can´t allowed to make and I am basically trying to do two things at once.
Is there any other to do this that the variable will be refreshed even without that println and the code will work ?
Thanks very much for every help
Thanks everybody for help, I finally solved it. I just tried tu put a sleep before the if condition. It only need to sleep for even a one miliseconds and it´s seems that the condition is refreshed so it works.
Try this:
Implement an ActionListener interface or extend a class that implements an ActionListener interface. For example:
public class MyClass implements ActionListener {
}
Register an instance of the event handler class as a listener on one or more components. For example:
someComponent.addActionListener(instanceOfMyClass);
instanceOfClass = this; //(if it is handled in the same Class)
Include code that implements the methods in listener interface. For example:
public void actionPerformed(ActionEvent e) {
...//code that reacts to the action...
}
Reference:
https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html
I am working on a school project that involves generating two separate Swing Canvas objects which animate Breadth/Depth-First Search Algorithms on cloned copies of a Matrix/Grid Data Structure I have designed.
I have created a few classes that help translate the Matrix/Grid into graphics, which are combined in a SearchAnimation class that acts a ViewController for managing the animations. In the image below, they appear on the right (not in the yellow background area). Each SearchAnimation object includes a JLabel, Canvas, and White Background.
Below is a screenshot of the layout:
The JFrame contains two instances of the SearchAnimation Class in the Application Controller Class (ICL.java). These animations must run concurrently. I have created separate Threads for each animation, passing it separate SearchAnimation objects:
public void setupDepthFirstPanel() {
// Create a new GridGraphic Panel
//canvasDepthFirst = new GridPanel(null, DEPTH_FIRST_LABEL);
mDepthAnimation = new SearchAnimation(null, SearchAnimationType.DEPTH_FIRST_ANIMATION);
mDepthThread = new Thread(mDepthAnimation, "Depth Thread");
}
public void setupBreadthFirstPanel() {
// Create a new GridGraphic Panel
//canvasBreadthFirst = new GridPanel(null, BREADTH_FIRST_LABEL);
mBreadthAnimation = new SearchAnimation(null, SearchAnimationType.BREADTH_FIRST_ANIMATION);
mBreadthThread = new Thread(mBreadthAnimation, "Breadth Thread");
}
I start the Threads in the ActionListener class that responds to the Click Event of the button that labeled "Label Components":
if ( source == labelComponents ) {
if (DEBUG && DEBUG_CLICK_LISTENER) System.out.println("\"Label Components\" Button Clicked!");
/*This is where the call for the labelBreadth and labelDepth of the
ICLLogic class is going to occur*/
// Run Animation
// Set Up Threads
System.out.println("ICL.ActionPerformed - Current Thread: " + Thread.currentThread());
//mBreadthThread = new Thread(mBreadthAnimation, "Breadth Animation");
//mDepthThread = new Thread(mDepthAnimation, "Depth Animation");
// Start Threads
mBreadthThread.start();
mDepthThread.start();
}
When the program runs and the "Label Components" button is clicked, only one of the graphics starts animating, but it seems as though both SearchAnimation Threads are running within a single JPanel/Canvas since the animation does not follow the logic of either algorithm.
Here is the implementation of the Runnable Interface within SearchAnimation:
// THREAD METHODS
/** Implementation of the Runnable interface for Multithreading of the
* SearchAnimation Class, which allows multiple SearchAnimations to run Concurrently.
* In this case, the Breadth & Depth-First SearchAnimations
*
*/
public void run() {
System.out.println("Thread Started - " + mAnimationType.toString());
// Run the Animation
step();
}
Which eventually calls determineSearchType() that switches on an Enum to pick the appropriate Algorithm:
public void determineSearchType(Pixel p) {
// Animate a single pixel movement, step depends on AnimationType
if (DEBUG && DEBUG_STEP_NEXT_PIXEL) { System.out.println("Determining Animation Type..."); }
switch (mAnimationType) {
case BREADTH_FIRST_ANIMATION:
if (DEBUG && DEBUG_STEP_NEXT_PIXEL) { System.out.println("Animation Type: Breadth-First"); }
// Begin Breadth-First Search
stepBreadthSearch(p);
break;
case DEPTH_FIRST_ANIMATION:
if (DEBUG && DEBUG_STEP_NEXT_PIXEL) { System.out.println("Animation Type: Depth-First"); }
// Begin Depth-First Search
stepDepthSearch(p);
//simpleDepthSearch(mCurrentPixel);
break;
}
}
When I alternate commenting them out, each Thread/Animation executes in its own JPanel/Canvas graphic and produces the expected results. I am pretty new to threading and I'm sure someone has an easy solution. Any ideas at how I can fix the issue that the animations won't animate simultaneously?
option1 :
to give another Thread chance to be executed. at the end of thread code, try yield() and see if you have some luck
Thread.currentThread().yield();
option2 :
add flag in your thread, to pause and continue the thread. the idea is
after thread 1 finish the step
- pause thread 1 - then start thread 2 - after thread 2 finish the step
- pause thread 2 - and continue thread 1 again.