I create some node in javaFX. And I need to animate each node to translate between some point to some point in Pane with TranslateTransition. But I need to make each of that node move independently using different starting point. How to make this happen? I mean is there any something like Thread.pause in javaFX. I tried using the rough approach like in the code below:
public void mouseRespon(final double x, final double y){
animasi.pause();
thread = new Thread(
new Runnable() {
#Override
public void run() {
int i = 0;
while(threadStatus && i < allList.size()){
final int j = i;
Platform.runLater(new Runnable() {
#Override
public void run() {
DynamicsText text = allList.get(j);
TranslateTransition transition = new TranslateTransition();
transition.setNode(text);
transition.setFromX(text.getTranslateX());
transition.setFromY(text.getTranslateY());
text.setDestinyOffset(x, y);
text.initCurrentOffSet();
double destX = text.getPotitionX();
double destY = text.getPotitonY();
transition.setToX(destX);
transition.setToY(destY);
transition.setDuration(Duration.seconds(1));
transition.setAutoReverse(false);
transition.setCycleCount(1);
transition.play();
}
});
try{
Thread.sleep(25);
}catch(Exception e){}
i++;
}
}
});
thread.start();
animasi.play();
}
But I think that is not a good approach. And actually, when I run that snippet make a program crash (sometime) .
Create a ParallelTransition.
For each piece that you want to move, create a SequentialTransition, a PauseTransition, and the TranslateTransition. The PauseTransitions should be incrementally bigger for each piece, say 0, 25ms, 50ms, 75ms, etc. Add the PauseTransition and the TranslateTransition to the SequentialTransition. Add each SequentialTransition to the ParallelTransition.
Then play the ParallelTransition.
No need to create any Threads or mess with Platform.runLater(...).
Related
I try to design a GUI for a neural network I made recently. I am using the MNIST-dataset and want to display the handwritten digit using JPanels with the brightness-values written inside. By pressing the "train"-button the network gets trained and every new digit is displayed. However this happens in a for loop in the actionperformed method of the button and it seems that I can´t change the background of the labels or the text(at least it doesn´t display the changes) until the last one. I don´t know whether I´m right but it seems that only the last change gets displayed. That´s why my question is whether it is possible to "refresh" the JFrame inside the actionperformed method.
I already have tried revalidate(), invalidate() & validate(), SwingUtilities.updateComponentTreeUI(frame), but none of them worked.
Here is the relevant part of my code:
train.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < iMax; i++) {
...
digitRefresh(reader.getInputs()[i], (int) reader.getInputs()[i][0], 0);
}
}
});
.
public void digitRefresh(double[] pixelValue, int target, int result) {
for (int i = 0; i < 784; i++) {
double value = pixelValue[i + 1];
int brightness = (int) (value * 255);
l_digit[i].setText(String.valueOf(value));
l_digit[i].setBackground(new Color(brightness, brightness, brightness));
}
l_target.setText(String.valueOf(target));
l_result.setText(String.valueOf(result));
this.revalidate();
}
thank you for every awnser and sorry for my bad english.
The simplest thing to do is start a new thread.
#Override
public void actionPerformed(ActionEvent e) {
new Thread( ()->{
for (int i = 0; i < iMax; i++) {
...
final int fi = i;
EventQueue.invokeLater( ()->{
digitRefresh(reader.getInputs()[fi], (int) reader.getInputs()[fi][0], 0);
});
}).start();
}
Now all of the work is being done on a separate thread, then as the ... work finishes, digit refresh method called from the EDT. Notice the final int fi part. There are caveats about going back and forth on threads so it is good to look into better controls than just using thread.
Swing worker for example:
How do I use SwingWorker in Java?
I have problem with updating JavaFX UI - I want to update line chart and some labels on my scene when it's already shown.
My task is to do some calculations (calling function in other class which returns dataseries) and add updated series to the chart.
The following code (which is in a loop) may present what i want to do:
//double x - x value of the point i want to add to my chart
//double y - y value of the point i want to add to my chart
//string s - some result from function
mySeries.getData().add(new XYChart.Data(x, y));
someLabel.setText(s);
My program freezes and give only final solution after some time, but i want to see the points on the chart exactly after they're added, not at the end of the execution. If the process is too quick, i would like to add Thread.sleep(1000) before adding the next point to the chart.
I know it has something to do with threads, concurrency and tasks, but i wasn't able to find a solution yet. I tried to use some code I found here but still I don't know the correct answer.
Every user action, e.g. click a button, will notify your action listener within the UI thread. Logic in the UI thread should be as fast as possible. I think you are reacting on a user event and then execute a long running task in the UI thread. Try to put your code in a background thread. Further you need to put the UI updates back again in the UI thread. You can do this with "Platform.runLater(...)".
Something like this:
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
Scene scene = new Scene(createChart());
primaryStage.setScene(scene);
primaryStage.setHeight(800);
primaryStage.setWidth(1200);
primaryStage.show();
}
private Parent createChart() {
LineChart<Number, Number> lc = new LineChart<>(new NumberAxis(), new NumberAxis());
XYChart.Series<Number, Number> series = new XYChart.Series<>();
lc.getData().add(series);
new Thread(() -> {
try {
Thread.sleep(5000);
for (int i = 0; i < 15; i++) {
int finalI = i;
Platform.runLater(() -> series.getData().add(new XYChart.Data<>(1 + finalI, 1 + finalI)));
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
return lc;
}
}
really need your help.
Im tryng to do a delay in Canvas.
I have a path inside of a list to paint and i'm tryng to paint point by point inside of that list.
I'm using handler(and i tryied Timer also) but it is an inner class so i cant access the index(int i) that is used on for.
Where is what i'm tryng to do:
for (int i = 0; i < path.size(); i++) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
c.drawCircle(path.get(i).getxPosition(), path.get(i).getyPosition(), 3, painter);
}
}, 5 * 1000);
}
Thanks,
Stuart
I am having this odd issue, and I am not sure what is causing it. Some times the issue isn't even there. From what I am guessing, is that this is a Java memory issue or some sort of threading issue.
I have a Ship and the ship shoots Bullets If I hold down the Space key the ship shoots the bullets. I have the bullets set to fire off every 200 milliseconds. Some times they shoot fine and move at the same speed! Other times, they shoot they move at different speeds. What could cause this?
package JGame.Actions;
import JGame.GameObject.GameObject;
import javax.swing.AbstractAction;
public class MoveAction extends Action implements Runnable{
protected GameObject obj;
protected int endX = 0, endY = 0;
protected int moveAmount = 0;
protected Thread thread;
public void moveToY(GameObject obj, int y, int amount, AbstractAction complete){
this.obj = obj;
this.endY = y;
this.moveAmount = amount;
this.complete = complete;
thread = new Thread(this);
thread.start();
}
public void run(){
try{
boolean run = true;
while(run){
int objY = obj.getY();
if(objY > this.endY){
obj.setY(obj.getY() - 1);
}else if(objY < this.endY){
obj.setY(obj.getY() + 1);
}else{
run = false;
this.actionComplete();
}
thread.sleep(moveAmount);
}
}catch(Exception e){
}
}
}
Action Complete:
package JGame.Actions;
import javax.swing.AbstractAction;
public class Action {
protected boolean actionComplete = false;
protected AbstractAction complete;
public void actionComplete(){
complete.actionPerformed(null);
}
}
In my code I call moveToY it is a very simple call but sometime the Bullets move at different speeds (wrong), and others they move at the same speed (right). I don't know if it would help to mention that as the bullets move sometimes they slow down for a second or two then speed back up to the correct speed.
Edit: Main Thread
The following is my main thread with the paintComponent
#Override
public void run(){
try{
while(true){
// Check for key press events
Iterator actions = KeyboardMap.map.entrySet().iterator();
while(actions.hasNext()){
Map.Entry ap = (Map.Entry)actions.next();
Mapping mp = (Mapping)ap.getValue();
if(mp.pressed){
mp.run();
}
}
// Check for click mouse events
Iterator actions2 = MouseMap.map.entrySet().iterator();
while(actions2.hasNext()){
Map.Entry ap = (Map.Entry)actions2.next();
Mapping mp = (Mapping)ap.getValue();
if(mp.pressed){
mp.run();
}
}
for(GameObject go : gameObjects){
if(!go.getLeaveScreen()){
int goWidth = go.getWidth();
int goHeight = go.getHeight();
int goX = go.getX();
int goY = go.getY();
int gameWidth = Game.width;
int gameHeight = Game.height;
if(goX + goWidth >= gameWidth){
go.setX(gameWidth - goWidth);
}
if(goX <= 0){
go.setX(0);
}
if(goY + goHeight >= gameHeight){
go.setY(gameHeight - goHeight);
}
if(goY <= 0){
go.setY(0);
}
}
}
this.repaint();
Thread.sleep(roomSpeed);
}
}catch(Exception e){
}
}
public void paintComponent(Graphics g){
try{
g.drawImage(bg, 0, 0, this);
for(int i = 0; i < gameObjects.size(); i++){
GameObject go = gameObjects.get(i);
g.drawImage(go.getSprite(), go.getX(), go.getY(), this);
}
}catch(Exception e){
}
}
Well, I guess you have a large number of concurrent threads running (one by moving bullet), and you expect each thread to wake up after exactly moveAmount milliseconds. You can't have such a guarantee, because the thread scheduler allows each thread to run for some time one at a time, and you might thus have glitches.
Another problem is that you seem to execute modification on Swing components out of the event dispatch thread, which is clearly forbidden by Swing's threading policy.
The most important thing to change in your code is don't model time with Thread.sleep. Use a Swing Timer, which you'll schedule to execute every moveAmount milliseconds and, as a bonus, the code is executed on the Event Dispatch Thread with no effort on your part.
Inform yourself about the usage of multiple threads and how the processing structure of a game is made correctly.
The most important info for your case: You should only use ONE thread to process/move all your bullets and then render them.
This is a java game that I have started working on.I have been trying to add a button that says "RESTART" which on clicking resets the whole program the way it was when it was at the beginning( i mean at the start of the game).
Here is my code:
There are 2 buttons namely "PLAY" & "CHECK WHO WON!"
For "PLAY" This is the code:
int delay = 1000;
final Timer timer = new Timer();
timer.schedule(new TimerTask(){
public void run(){
String b = "C:\\Users\\COMPUTER\\Desktop\\deck\\.png";
Random r = new Random();
r1 = r.nextInt(upplim)+lolim;
String a = Integer.toString(r1);
String c = "C:\\Users\\COMPUTER\\Desktop\\deck\\"+a+".png";
l1.setIcon(new ImageIcon(c));
}
},delay, 50);
For "CHECK WHO WON!" This is the code:
final int p = h;
System.out.println("ANSWER IS:"+p);
int delay2 = 1000;
for (int i = 1; i < 53; i++)
{
while(true)
{
next = rng.nextInt(Ulim) + Llim;
if (!generated.contains(next))
{
generated.add(next);
break;
}
}
if ( i % 2 == 0 )
{count++;
deck1[e] = next;deck1count++;
e++;
}
else {count++;
deck2[f] = next;deck2count++;
f++;
}
System.out.println(""+next);
if(next==p)
{break;}
}
if(deck1count==deck2count)
{
count=count-2;
fcard=99;}
final Timer timer2 = new Timer();
timer2.schedule(new TimerTask(){
public void run(){
do
{
System.out.println("dec2 "+deck2[z]);
String a = Integer.toString(deck2[z]);
String c = "C:\\Users\\COMPUTER\\Desktop\\deck\\"+a+".png";
l3.setIcon(new ImageIcon(c));
System.out.println("dec1 "+deck1[z]);
String b = Integer.toString(deck1[z]);
String d = "C:\\Users\\COMPUTER\\Desktop\\deck\\"+b+".png";
l4.setIcon(new ImageIcon(d));
System.out.println("count"+count);
z++;
count=count-2;
if(fcard==99&&count<0)
{l3.setIcon(new ImageIcon("C:\\Users\\COMPUTER\\Desktop\\deck\\99.png"));
}
}while(count>0&&z==p);
if(count<0)
{timer2.cancel();
reschk=11;
timer2.purge();
}
}
},delay2, 1000);
There is also another set of code which is written on the MouseClicked event of a label but I don't think it would be of much help here.
I have tried:
classname.this.dispose();
classname classname = new classname();
But it just shuts the whole program down.Is there any other way to reset the game?
Thanks for reading.
Any help would be appreciated.
You obviously have values which update so that you can represent your game during different states. If you want to restart your game, you simply need to set all of these values back to the original start values. You can write a Restart method to this.
Also, dispose() is designed to close the window.
edit: There is no magic method you can call to reset your program.
For Swing based container use Swing Timer rather than util.Timer, otherwise output from util.Timer should be out of EDT.
You don't need to dispose old container and recreate a new for fresh game, you can remove its contents.
anything else isn't clear from code posted here, nor question
Keep the state of the game in a distinct class and replace that with a fresh instance.