Moving circle changing color in javafx - java

I want my ball to change color everytime i click on it, but i wont get it to work. Also im wondering about the movement of my ball. I wonder how you can change the path its going. so it can down up and down and other ways instead of just from left to right.
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.Bloom;
import javafx.scene.effect.Effect;
import javafx.scene.effect.Glow;
import javafx.scene.effect.Light;
import javafx.scene.effect.Lighting;
import javafx.scene.effect.MotionBlur;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TimelineSample extends Application {
Timeline timeline;
private void init(Stage primaryStage) {
Group root = new Group();
primaryStage.setResizable(false);
primaryStage.setScene(new Scene(root, 280, 120));
Circle circle = new Circle(25, 25, 20, Color.BLUE);
Light.Distant light = new Light.Distant();
light.setAzimuth(-135.0);
Lighting lighting = new Lighting();
lighting.setLight(light);
lighting.setSurfaceScale(5.0);
circle.setEffect(lighting);
timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.setAutoReverse(true);
timeline.getKeyFrames().addAll
(new KeyFrame(Duration.ZERO, new KeyValue(circle.translateXProperty(),
0)),
new KeyFrame(new Duration(4000), new KeyValue(circle
.translateXProperty(), 205)));
root.getChildren().add(circle);
root.requestFocus();
root.setOnKeyPressed(e -> {
if (e.getCode().equals(KeyCode.ENTER)) {
timeline.play();
circle.setFill(Color.PINK);
}
});
root.setOnMousePressed(event -> {
if (circle.contains(event.getX(), event.getY())) {
circle.setFill(Color.BLACK);
if (circle.getFill().equals(Color.BLACK))
circle.setFill(Color.YELLOW);
else if (circle.getFill().equals(Color.BLUE))
circle.setFill(Color.BROWN);
else if (circle.getFill().equals(Color.YELLOW))
circle.setFill(Color.BROWN);
else if (circle.getFill().equals(Color.BROWN))
circle.setFill(Color.BLACK);
}
});
}
#Override
public void stop() {
timeline.stop();
}
#Override
public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

It does not change the color (just once to yellow) because before your check you set it to black and then it is converted to yellow.
if (circle.contains(event.getX(), event.getY())) {
circle.setFill(Color.BLACK); // <-- so it is black
if (circle.getFill().equals(Color.BLACK)) // <-- uhh..it is black..let's change to yellow
circle.setFill(Color.YELLOW);
else if (circle.getFill().equals(Color.BLUE))
circle.setFill(Color.BROWN);
else if (circle.getFill().equals(Color.YELLOW))
circle.setFill(Color.BROWN);
else if (circle.getFill().equals(Color.BROWN))
circle.setFill(Color.BLACK);
}
And it is getting from left to right because your using the X-Property instead of the Y-Property.

Related

Update JavaFX stage within method

I am writing a program that uses a lot of data to do several calculations and it takes quite a while to finish. This is why I want to update and inform the user on the current percentage of the program being done. However I don't know how I can update the stage within the calculation method.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
public void calculate() {
//Here I want to change the "percentage text"
//and update the stage.
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Text percentage = new Text();
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
calculate();
}
});
final GridPane inputGridPane = new GridPane();
GridPane.setConstraints(btn, 0, 0);
GridPane.setConstraints(percentage, 1, 0);
inputGridPane.setHgap(6);
inputGridPane.setVgap(6);
inputGridPane.getChildren().addAll(btn, percentage);
final Pane rootGroup = new VBox(12);
rootGroup.setPrefWidth(400);
rootGroup.setPrefHeight(225);
rootGroup.getChildren().addAll(inputGridPane);
rootGroup.setPadding(new Insets(12,12,12,12));
primaryStage.setScene(new Scene(rootGroup));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
This is what my code roughly looks like. Thank you in advance.
JavaFx provides a class called "Task" which can be used for background calculations while keeping the progression syncronised!
I would suggest doing it that way:
Create a second class extending Task for doing the heavy calculation:
import javafx.concurrent.Task;
public class CalculationTask extends Task<String> {
#Override
protected String call() throws Exception {
for (int i = 0; i < 100000000;i++) {
updateProgress(i, 100000000);
}
succeeded();
return "This is the computed result... Datatype can be changed by generics if you are calculation numbers";
}
}
This is one way how you could use it in your application class:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Dialog;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World!");
Button btn = new Button();
btn.setText("Say 'Hello World'");
Task<String> calculationTask = new CalculationTask();
ProgressBar progressBar = new ProgressBar(); //ProgressIndicator could also be used
progressBar.progressProperty().bind(calculationTask.progressProperty());
progressBar.visibleProperty().bind(calculationTask.runningProperty());
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
calculationTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent workerStateEvent) {
new Alert(Alert.AlertType.CONFIRMATION, calculationTask.getValue()).show();
}
});
new Thread(calculationTask).start();
}
});
final GridPane inputGridPane = new GridPane();
GridPane.setConstraints(btn, 0, 0);
GridPane.setConstraints(progressBar, 1, 0);
inputGridPane.setHgap(6);
inputGridPane.setVgap(6);
inputGridPane.getChildren().addAll(btn, progressBar);
final Pane rootGroup = new VBox(12);
rootGroup.setPrefWidth(400);
rootGroup.setPrefHeight(225);
rootGroup.getChildren().addAll(inputGridPane);
rootGroup.setPadding(new Insets(12,12,12,12));
primaryStage.setScene(new Scene(rootGroup));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I hope that helped, otherwise feel free to ask questions!

javaFX circle in a layout not visible

I made a circle and added as a child to a group. then I added the group as a child to a layout(Region). I added Region to the scene. I made both with different colours but I cannot see the circle
Analog_clock.java
package analog_clock;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Analog_clock extends Application {
#Override
public void start(Stage primaryStage) {
Circle circle = new Circle();
circle.setCenterX(100.0f);
circle.setCenterY(100.0f);
circle.setRadius(50.0f);
circle.setFill(Color.ALICEBLUE);
Group g = new Group();
g.getChildren().add(circle);
Background_region_ bg = new Background_region_();
bg.getChildrenUnmodifiable().add(g);
Scene scene = new Scene(bg, 300, 250);
scene.getStylesheets().add(this.getClass().getResource("style.css").toExternalForm());
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Background_Region_.java
package analog_clock;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Background_region_ extends Region
{
//CONSTRUCTOR
public Background_region_()
{
setStyle("-fx-background-color: #ACACE6");
}
}
style.css
.circle{-fx-stroke: #cdd0d7;}
The problem is the Region Class only has an Unmodifiable List of children via its public API, that means, the only way to add children to it is to subclass it (e.g Pane). So use Pane or another subclass, something like this for example:
Pane bg = new Pane();
bg.setBackground(new Background(new BackgroundFill(Color.web("#ACACE6"), null,null)));
bg.getChildren().add(g);
Use Pane instead of Region. Region is a special parent class for control's developers.
Next line throws exception in your code:
bg.getChildrenUnmodifiable().add(g);
Note word "Unmodifiable". It means your are not supposed and can't modify this list.

ProgressIndicator (Node) as a mouse cursor?

Is it possible to use a Node as a mouse cursor? I'm thinking in a ProgressIndicator. For example a determinate one, letting the user know how much percentage of the current task is done.
Probably the most reliable way to do this is to set the cursor to Cursor.NONE, and have a label with the progress indicator as its graphic, which tracks the mouse coordinates.
I tried using an ImageCursor which updated, but nothing appeared: I am guessing the images couldn't be computed quickly enough.
Here's an SSCCE of the first technique:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.ImageCursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class ProgressIndicatorAsCursor extends Application {
#Override
public void start(Stage primaryStage) {
Button button = new Button("Start");
Service<Void> service = new Service<Void>() {
#Override
public Task<Void> createTask() {
return new Task<Void>() {
#Override
public Void call() throws Exception {
for (int i = 1 ; i <= 1000; i++) {
Thread.sleep(10);
updateProgress(i, 1000);
}
return null ;
}
};
}
};
button.disableProperty().bind(service.runningProperty());
button.setOnAction(e -> service.restart());
ProgressIndicator pi = new ProgressIndicator();
pi.progressProperty().bind(service.progressProperty());
Pane pane = new Pane();
// fill pane with rectangle as task progresses:
Rectangle rectangle = new Rectangle();
rectangle.setFill(Color.CORNFLOWERBLUE);
rectangle.setX(0);
rectangle.widthProperty().bind(pane.widthProperty());
rectangle.heightProperty().bind(pane.heightProperty().multiply(service.progressProperty()));
rectangle.yProperty().bind(pane.heightProperty().subtract(rectangle.heightProperty()));
pane.getChildren().add(rectangle);
Label label = new Label();
label.graphicProperty().bind(
Bindings.when(service.runningProperty())
.then(pi)
.otherwise((ProgressIndicator)null));
pane.setOnMouseEntered(e ->
pane.getChildren().add(label));
pane.setOnMouseExited(e ->
pane.getChildren().remove(label));
pane.setOnMouseMoved(e -> label.relocate(e.getX(), e.getY()));
pane.cursorProperty().bind(
Bindings.when(service.runningProperty())
.then(Cursor.NONE)
.otherwise(Cursor.DEFAULT));
BorderPane.setAlignment(button, Pos.CENTER);
BorderPane.setMargin(button, new Insets(10));
BorderPane root = new BorderPane(pane, new Rectangle(0,0,0,20), null, button, null);
primaryStage.setScene(new Scene(root, 400, 600));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Sees it's impossible, but you could obtain the cursor property and keep updating it with an image as your desire.

BorderPane is hiding bottom region until window is maximized

BorderPane in JavaFx application does not show bottom region Node unless the window is maximized when the scene is switched using Button event. If the scenes are switched one after another its arranged perfectly. Do I have bugs in my code or is this the default behaviour? Thanks.
System : Windows XP
Java version : 7
My SSCE:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class Main extends Application {
#Override
public void start(final Stage stage) {
try {
///// 2nd scene
BorderPane root2 = new BorderPane();
root2.setPrefSize(stage.getWidth(),stage.getHeight());
HBox buttons2=new HBox(50);
buttons2.getChildren().addAll(new Button("Button1"),new Button("Button2"));
buttons2.setAlignment(Pos.BOTTOM_CENTER);
root2.setBottom(buttons2);
final Scene scene2 = new Scene(root2,stage.getWidth(),stage.getHeight());
///// 1st scene
VBox buttons1=new VBox();
buttons1.setPrefSize(stage.getWidth(),stage.getHeight());
Button nextSceneBtn=new Button("NEXT");
buttons1.getChildren().add(nextSceneBtn);
buttons1.setAlignment(Pos.CENTER);
Scene scene1=new Scene(buttons1,stage.getWidth(),stage.getHeight());
////action event
nextSceneBtn.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
stage.setScene(scene2);
}
});
///stage
Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
stage.setX(0);
stage.setY(0);
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.setScene(scene1); //if it's #setScene(scene2) at the beginning, it's ok
stage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
That looks like a bug, which seems to have been fixed in JavaFX 8. Obviously if you're running on Windows XP, that's of limited use.
A possible workaround is to switch the root of the scene, instead of the scene itself:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.stage.Screen;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
public class Main extends Application {
#Override
public void start(final Stage stage) {
try {
///// 2nd scene
final BorderPane root2 = new BorderPane();
root2.setPrefSize(stage.getWidth(),stage.getHeight());
HBox buttons2=new HBox(50);
buttons2.getChildren().addAll(new Button("Button1"),new Button("Button2"));
buttons2.setAlignment(Pos.BOTTOM_CENTER);
root2.setBottom(buttons2);
// final Scene scene2 = new Scene(root2,stage.getWidth(),stage.getHeight());
///// 1st scene
VBox buttons1=new VBox();
buttons1.setPrefSize(stage.getWidth(),stage.getHeight());
Button nextSceneBtn=new Button("NEXT");
buttons1.getChildren().add(nextSceneBtn);
buttons1.setAlignment(Pos.CENTER);
final Scene scene1=new Scene(buttons1,stage.getWidth(),stage.getHeight());
////action event
nextSceneBtn.setOnMouseClicked(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent event) {
// stage.setScene(scene2);
scene1.setRoot(root2);
}
});
///stage
Screen screen = Screen.getPrimary();
Rectangle2D bounds = screen.getVisualBounds();
stage.setX(0);
stage.setY(0);
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.setScene(scene1); //if it's #setScene(scene2) at the beginning, it's ok
stage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}

Can't instantiate Path() class on Javafx 2.0

I'm learning javafx.
I'm trying to make a path, but when i instantiate the class Path(), i receive the following message: "java.nio.file.Path is abstract; cannot be instantiated"
package mapas;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.BoxBlur;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;
import java.nio.file.Path;
import javax.sound.midi.Patch;
public class Mapas extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Group root = new Group();
Group circles = new Group();
Scene scene = new Scene(root, 800, 600, Color.BLACK);
primaryStage.setScene(scene);
circles.setEffect(new BoxBlur(10, 10, 3));
primaryStage.show();
for(int i = 0; i < 30; i++){
Circle circle = new Circle(150, Color.web("white", 0.05));
circle.setStrokeType(StrokeType.OUTSIDE);
circle.setStroke(Color.web("white", 0.16));
circle.setStrokeWidth(4);
circles.getChildren().add(circle);
}
root.getChildren().add(circles);
Path path = new Path(); // <-- error
}
}
What's wrong?
Are you sure you want to import java.nio.file.Path as opposed to javafx.scene.shape.Path?????

Categories