Mohsin Anees Mohsin Anees - 4 months ago 20
Java Question

Javafx Gui update

My problem is basically from Java language which I cannot figure out.
This is just a basic code to help me understand the concept of updating GUI using

Platform.runlater
method.

package practise;

import java.util.Random;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.stage.Stage;

public class Practise extends Application {

@Override
public void start(Stage primaryStage) {
Button btn = new Button();
final Line l1 = new Line(200,80,200,0);
final int c = 0;

btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {

@Override
public void handle(ActionEvent event) {
System.out.println("Hello World!");

Platform.runLater(new Runnable() {
Random rn = new Random();
@Override

public void run() {
if(c==0)
{
l1.setStartX(rn.nextInt(400));
l1.setStartY(rn.nextInt(400));
c = 1;
}
else
{
l1.setEndX(rn.nextInt(400));
l1.setEndY(rn.nextInt(400));
c = 0;
}
}
});
}
});


l1.setStroke(Color.YELLOW);
l1.setStrokeWidth(2);

StackPane root = new StackPane();
root.getChildren().add(btn);
root.getChildren().add(l1);

Scene scene = new Scene(root, 400, 400, Color.WHITE);

primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}

public static void main(String[] args) {
launch(args);
}

}


This is my code. I wish to alternatingly change either the start point or the end points of the lines. For that I created a variable 'c' which alternates it's values every time I press the button.

But the issue is that the compiler forces me to change int c into final. Which means it becomes a constant and no longer serves my purpose.

Why is this happening and how can I get around it?

Answer

You're using a variable with local scope in an anonymous inner class. You can only do this if the variable is final. If you need to change the value of the variable, you could define it as an instance variable.

public class MainApp extends Application {

    private int c;

    @Override
    public void start(Stage primaryStage) {
        Button btn = new Button();
        final Line l1 = new Line(200,80,200,0);

        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                System.out.println("Hello World!");

                Platform.runLater(new Runnable() {
                    Random rn = new Random();
                    @Override

                    public void run() {
                        if(c==0)
                        {
                            System.out.println("c=" + c);
                            l1.setStartX(rn.nextInt(400));
                            l1.setStartY(rn.nextInt(400));
                            c = 1;
                        }
                        else
                        {
                            System.out.println("c=" + c);
                            l1.setEndX(rn.nextInt(400));
                            l1.setEndY(rn.nextInt(400));
                            c = 0;
                        }
                    }
                });
            }
        });


        l1.setStroke(Color.YELLOW);
        l1.setStrokeWidth(2);

        StackPane root = new StackPane();
        root.getChildren().add(btn);
        root.getChildren().add(l1);

        Scene scene = new Scene(root, 400, 400, Color.WHITE);

        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}

Output after a couple of button clicks:

Hello World!
c=0
Hello World!
c=1
Hello World!
c=0