I am trying to animate the text fill of a Label on JavaFX (Using JavaFX 8).
My goal is to make the First color of the gradient to change from yellow to red every half second.
I have tried this:
Timeline timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
timeline.setAutoReverse(true);
LinearGradient fill1 = new LinearGradient(50,50,200,200,false, CycleMethod.NO_CYCLE, new Stop(0.1f, Color.YELLOW), new Stop(1.0f, Color.BLACK));
LinearGradient fill2 = new LinearGradient(50,50,200,200,false, CycleMethod.NO_CYCLE, new Stop(0.1f, Color.RED), new Stop(1.0f, Color.BLACK));
KeyValue keyValue1 = new KeyValue(labelInstrucoes.textFillProperty(), fill1, Interpolator.EASE_OUT);
KeyValue keyValue2 = new KeyValue(labelInstrucoes.textFillProperty(), fill2, Interpolator.EASE_OUT);
KeyFrame keyframe1 = new KeyFrame(Duration.millis(0), keyValue1);
KeyFrame keyframe2 = new KeyFrame(Duration.millis(500), keyValue2);
timeline.getKeyFrames().addAll(keyframe1, keyframe2);
timeline.play();
But it didn't work. However, if instead of LinearGradient i use a simple color, like this:
KeyValue keyValue1 = new KeyValue(labelInstrucoes.textFillProperty(), Color.YELLOW, Interpolator.EASE_OUT);
KeyValue keyValue2 = new KeyValue(labelInstrucoes.textFillProperty(), Color.RED, Interpolator.EASE_OUT);
It works. So, how to animate the gradient?
You can use a css trick for this, using looked-up colors.
In an external CSS file, define a looked-up color for the beginning of the linear gradient, and define the text fill using a linear gradient that references the looked-up color:
animated-gradient.css:
.animated-gradient {
-gradient-base: red ;
-fx-text-fill: linear-gradient(to right, -gradient-base, black);
}
Then "animate" a color property, and update the inline style to change the value of the looked-up color whenever the property changes:
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class AnimatedGradient extends Application {
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
Label label = new Label("Animated gradient");
root.getChildren().add(label);
label.getStyleClass().add("animated-gradient");
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("animated-gradient.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
ObjectProperty<Color> baseColor = new SimpleObjectProperty<>();
KeyValue keyValue1 = new KeyValue(baseColor, Color.RED);
KeyValue keyValue2 = new KeyValue(baseColor, Color.YELLOW);
KeyFrame keyFrame1 = new KeyFrame(Duration.ZERO, keyValue1);
KeyFrame keyFrame2 = new KeyFrame(Duration.millis(500), keyValue2);
Timeline timeline = new Timeline(keyFrame1, keyFrame2);
baseColor.addListener((obs, oldColor, newColor) -> {
label.setStyle(String.format("-gradient-base: #%02x%02x%02x; ",
(int)(newColor.getRed()*255),
(int)(newColor.getGreen()*255),
(int)(newColor.getBlue()*255)));
});
timeline.setAutoReverse(true);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
public static void main(String[] args) {
launch(args);
}
}
(You can use Bindings.format(...) instead of the listener, not much difference.)
Here is a solution without css. It can be used in animated Controls.
Below I posted the code of Application with two different elements. You can run it and see how it works.
1. This is Region with animated Background
public class FilledRegion extends Region {
private final Random rand;
private ObjectProperty<Color> externalColor = new SimpleObjectProperty();
private ObjectProperty<Color> internalColor = new SimpleObjectProperty();
private Color oldExternalColor;
private Color oldInternalColor;
private Background bg;
private Timeline timeline;
private int duration;
public FilledRegion() {
rand = new Random();
this.setMinWidth(75);
oldExternalColor = getRandomColor(AnimatedGradients.baseExternalColor, AnimatedGradients.externalDelta);
oldInternalColor = getRandomColor(AnimatedGradients.baseInternalColor, AnimatedGradients.internalDelta);
externalColor.set( oldExternalColor );
internalColor.set( oldInternalColor );
setBackground();
internalColor.addListener((obs, oldColor, newColor) -> {
setBackground();
});
}
public void startAnimation() {
timeline = new Timeline();
createTimelineContent();
timeline.setOnFinished(ActionEvent -> {
createTimelineContent();
timeline.play();
});
timeline.play();
}
private void createTimelineContent() {
timeline.getKeyFrames().clear();
duration = getRandomDuration();
KeyFrame kf1 =
new KeyFrame(Duration.ZERO,
new KeyValue( externalColor, oldExternalColor ),
new KeyValue( internalColor, oldInternalColor ));
oldExternalColor = getRandomColor(AnimatedGradients.baseExternalColor, AnimatedGradients.externalDelta);
oldInternalColor = getRandomColor(AnimatedGradients.baseInternalColor, AnimatedGradients.internalDelta);
KeyFrame kf2 =
new KeyFrame(new Duration(duration),
new KeyValue( externalColor, oldExternalColor ),
new KeyValue( internalColor, oldInternalColor ));
timeline.getKeyFrames().addAll( kf1, kf2 );
}
private void setBackground() {
bg = new Background(
new BackgroundFill(
new LinearGradient(0, 0, 0, 1, true, CycleMethod.NO_CYCLE,
new Stop[] { new Stop(0, externalColor.get()), new Stop(0.5, internalColor.get()), new Stop(1, externalColor.get())}
),
new CornerRadii(0),
new Insets(0, 0, 0, 0)
)
);
this.setBackground(bg);
}
private Color getRandomColor(Color color, double delta) {
int index = (int)( (color.getRed()+getRandomCoefficient(delta))*255 );
int r = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
index = (int)( (color.getGreen()+getRandomCoefficient(delta))*255 );
int g = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
index = (int)( (color.getBlue()+getRandomCoefficient(delta))*255 );
int b = ( index > 255 ) ? 255 : ( (index < 0) ? 0 : index );
return Color.rgb(r, g, b);
}
private double getRandomCoefficient(double delta) {
return ( rand.nextDouble()*2 - 1 ) * delta;
}
private int getRandomDuration() {
return (int)(( rand.nextDouble()*2 - 1 ) * AnimatedGradients.durationDelta * AnimatedGradients.baseDuration) + AnimatedGradients.baseDuration;
}}
2. This is example of animated Icon
public class AnimatedIcon extends WritableImage {
private ObjectProperty<Color> topColor = new SimpleObjectProperty();
private ObjectProperty<Color> bottomColor = new SimpleObjectProperty();
private Color oldTopColor;
private Color oldBottomColor;
private Timeline timeline;
private static final int DURATION = 5000;
private static final Random rand = new Random();
private static final int ICON_WIDTH = 32;
private static final int ICON_HEIGHT = 32;
private Stage primaryStage;
public AnimatedIcon(Stage primaryStage) {
super(ICON_WIDTH, ICON_HEIGHT);
this.primaryStage = primaryStage;
oldTopColor = Color.rgb(0, 45, 0);
oldBottomColor = Color.rgb(12, 128, 12);
topColor.set(oldTopColor);
bottomColor.set(oldBottomColor);
createGraphics();
bottomColor.addListener((obs, oldColor, newColor) -> {
createGraphics();
});
}
private void createGraphics() {
PixelWriter pixelWriter = this.getPixelWriter();
for (int y = 0; y < ICON_HEIGHT; y++) {
for (int x = 0; x < ICON_WIDTH; x++) {
double position = (double)x/(double)ICON_WIDTH;
int r = (int)( ( topColor.get().getRed() - (topColor.get().getRed() - bottomColor.get().getRed())*position ) * 255 );
int g = (int)( ( topColor.get().getGreen() - (topColor.get().getGreen() - bottomColor.get().getGreen())*position ) * 255 );
int b = (int)( ( topColor.get().getBlue() - (topColor.get().getBlue() - bottomColor.get().getBlue())*position ) * 255 );
double o = topColor.get().getOpacity() - (topColor.get().getOpacity() - bottomColor.get().getOpacity())*position;
pixelWriter.setColor(x,y,Color.rgb(r,g,b,o));
}
}
int index = primaryStage.getIcons().indexOf(this);
if (index == 0) {
primaryStage.getIcons().set(index, this);
} else {
primaryStage.getIcons().add(this);
}
}
public void startAnimation() {
timeline = new Timeline();
createTimelineContent();
timeline.setOnFinished(ActionEvent -> {
createTimelineContent();
timeline.play();
});
timeline.play();
}
private void createTimelineContent() {
timeline.getKeyFrames().clear();
KeyFrame kf1 =
new KeyFrame(Duration.ZERO,
new KeyValue( topColor, oldTopColor ),
new KeyValue( bottomColor, oldBottomColor ));
oldTopColor = Color.rgb(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256), rand.nextDouble());
oldBottomColor = Color.rgb(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256), 1);
KeyFrame kf2 =
new KeyFrame(new Duration(DURATION),
new KeyValue( topColor, oldTopColor ),
new KeyValue( bottomColor, oldBottomColor ));
timeline.getKeyFrames().addAll( kf1, kf2 );
}}
This is the main class for elements located above
public class AnimatedGradients extends Application {
protected static int baseDuration = 10000;
protected static Color baseExternalColor = Color.rgb(0, 0, 0);
protected static Color baseInternalColor = Color.rgb(127, 127, 127);
protected static double durationDelta = 0.25;
protected static double externalDelta = 0.1;
protected static double internalDelta = 1;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
HBox root = new HBox();
root.setSpacing(1);
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 761, 500, Color.BLACK);
primaryStage.setScene(scene);
AnimatedIcon ai = new AnimatedIcon(primaryStage);
primaryStage.getIcons().add(ai);
ai.startAnimation();
primaryStage.setTitle("Animated Gradients");
for (int i = 0; i < 10; i++) {
FilledRegion gr = new FilledRegion();
root.getChildren().add(gr);
gr.startAnimation();
}
primaryStage.show();
}}
Related
I am creating a chess game and i am stuck at one thing for a couple of days.
So i want to create event when user moves over a figure the image of figure replaces to another image with border and when user moves away the image must return to normal. Here is full code.
Folder for Project is called sample,Folder for images is Called Sprites.
Folder for classes is called Figures.I will link the images for black pawn.
package sample;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import sample.Figures.*;
public class Main extends Application {
#Override
public void start(Stage primaryStage){
primaryStage.setTitle("ChessGame");
primaryStage.getIcons().add(new Image("/sample/Chess-icon.png"));
GridPane root = new GridPane();
final GridPane group = new GridPane();
group.setPadding(new Insets(15, 25, 25, 25));
for (int i = 0 ; i < 8 ; i++) {
for (int j = 0 ; j < 8 ; j++) {
Rectangle rectangle = new Rectangle( 50, 50);
if(j % 2 == 0 && (i % 2 == 0)) {
rectangle.setFill(Color.BEIGE);
}
else if(!((j + 2) % 2 == 0) && !((i + 2) % 2 == 0)) {
rectangle.setFill(Color.BEIGE);
}
else {
rectangle.setFill(Color.GRAY);
}
group.add(rectangle,i,j);
}
}
//FIGURES
//Black
//Pawns
final blackPawn BlackP_1 = new blackPawn(0,1,64,65);
group.add(BlackP_1.IMG,BlackP_1.x,BlackP_1.y);
BlackP_1.IMG.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
group.getChildren().remove(64,65);
group.add(BlackP_1.IMGglow,0,1);
}
});
BlackP_1.IMGglow.setOnMouseExited(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
group.getChildren().remove(64,65);
group.add(BlackP_1.IMG,BlackP_1.x,BlackP_1.y);
}
});
blackPawn BlackP_2 = new blackPawn(1,1);
group.add(BlackP_2.IMG,BlackP_2.x,BlackP_2.y);
blackPawn BlackP_3 = new blackPawn(2,1);
group.add(BlackP_3.IMG,BlackP_3.x,BlackP_3.y);
blackPawn BlackP_4 = new blackPawn(3,1);
group.add(BlackP_4.IMG,BlackP_4.x,BlackP_4.y);
blackPawn BlackP_5 = new blackPawn(4,1);
group.add(BlackP_5.IMG,BlackP_5.x,BlackP_5.y);
blackPawn BlackP_6 = new blackPawn(5,1);
group.add(BlackP_6.IMG,BlackP_6.x,BlackP_6.y);
blackPawn BlackP_7 = new blackPawn(6,1);
group.add(BlackP_7.IMG,BlackP_7.x,BlackP_7.y);
blackPawn BlackP_8 = new blackPawn(7,1);
group.add(BlackP_8.IMG,BlackP_8.x,BlackP_8.y);
//Rooks
blackRook BlackR_1 = new blackRook();
group.add(BlackR_1.IMG,7,0);
blackRook BlackR_2 = new blackRook();
group.add(BlackR_2.IMG,0,0);
//Knights
blackKnight BlackK_1 = new blackKnight();
group.add(BlackK_1.IMG,1,0);
blackKnight BlackK_2 = new blackKnight();
group.add(BlackK_2.IMG,6,0);
//Bishop
blackBishop BlackB_1 = new blackBishop();
group.add(BlackE_1.IMG,2,0);
blackBishop BlackB_2 = new blackBishop();
group.add(BlackE_2.IMG,5,0);
//Queen
blackQueen blackQueen= new blackQueen();
group.add(blackQueen.IMG,3,0);
//King
blackKing blackking = new blackKing();
group.add(blackking.IMG,4,0);
//WHITE
//Pawns
final whitePawn WhiteP_1 = new whitePawn();
group.add(WhiteP_1.IMG,0,6);
whitePawn WhiteP_2 = new whitePawn();
group.add(WhiteP_2.IMG,1,6);
whitePawn WhiteP_3 = new whitePawn();
group.add(WhiteP_3.IMG,2,6);
whitePawn WhiteP_4 = new whitePawn();
group.add(WhiteP_4.IMG,3,6);
whitePawn WhiteP_5 = new whitePawn();
group.add(WhiteP_5.IMG,4,6);
whitePawn WhiteP_6 = new whitePawn();
group.add(WhiteP_6.IMG,5,6);
whitePawn WhiteP_7 = new whitePawn();
group.add(WhiteP_7.IMG,6,6);
whitePawn WhiteP_8 = new whitePawn();
group.add(WhiteP_8.IMG,7,6);
//Rooks
whiteRook WhiteR_1 = new whiteRook();
group.add(WhiteR_1.IMG,0,7);
whiteRook WhiteR_2 = new whiteRook();
group.add(WhiteR_2.IMG,7,7);
//Knights
whiteKnight WhiteK_1 = new whiteKnight();
group.add(WhiteK_1.IMG,1,7);
whiteKnight WhiteK_2 = new whiteKnight();
group.add(WhiteK_2.IMG,6,7);
//Bishop
whiteBishop WhiteB_1 = new whiteBishop();
group.add(WhiteB_1.IMG,2,7);
whiteBishop WhiteB_2 = new whiteBishop();
group.add(WhiteB_2.IMG,5,7);
//Queen
whiteQueen whitequeen = new whiteQueen();
group.add(whitequeen.IMG,3,7);
//King
whiteKing whiteking = new whiteKing();
group.add(whiteking.IMG,4,7);
root.getChildren().add(group);
root.setStyle("-fx-background-color: #C1D1E8;");
Scene scene = new Scene(root, 450, 440);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Black Pawn Class
package sample.Figures;
import javafx.scene.image.ImageView;
public class blackPawn {
public int x;
public int y;
public int start;
public int end;
public ImageView IMG = new ImageView("sample/Sprites/blackPawn.png");
public ImageView IMGglow = new ImageView("sample/Sprites/blackPawnStroke.png");
public blackPawn(int x,int y)
{
this.x = x;
this.y = y;
}
public blackPawn(int x,int y,int start,int end)
{
this.x = x;
this.y = y;
this.start = start;
this.end = end;
}
}
It's quite easy to change the Image of an ImageView just by calling the setImage(). There are two ways to make the transition from one state to another. The first approach is programmatically through setOnMouseEntered() and setOnMouseExited() here is an example :
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class HoverableImage extends Application {
#Override
public void start(Stage stage) throws Exception {
ImageView imageView = createChestImage();
FlowPane pane = new FlowPane();
pane.setAlignment(Pos.CENTER);
pane.getChildren().add(imageView);
stage.setScene(new Scene(pane, 100, 100));
stage.show();
}
private ImageView createChestImage() {
ImageView iv = new ImageView(new Image("https://i.stack.imgur.com/rd71Q.png"));
iv.setOnMouseEntered(e->{
iv.setImage(new Image("https://i.stack.imgur.com/7JU7r.png"));
});
iv.setOnMouseExited(e->{
iv.setImage(new Image("https://i.stack.imgur.com/rd71Q.png"));
});
return iv;
}
public static void main(String[] args) {
launch(args);
}
}
The second approach would be to do that using CSS, you can set each chest piece an ID (for example : iv.setID("SoldierPiece"); ) and then apply those CSS rules on it :
#SoldierPiece{
-fx-image: url("https://i.stack.imgur.com/rd71Q.png");
}
#SoldierPiece:hover{
-fx-image: url("https://i.stack.imgur.com/7JU7r.png");
}
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.geometry.HPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class MPGCalc extends Application {
private TextField tfMiles = new TextField();
private TextField tfGallons = new TextField();
private TextField tfMiles1 = new TextField();
private TextField tfGallons1 = new TextField();
private TextField tfMiles2 = new TextField();
private TextField tfGallons2 = new TextField();
private TextField tfMiles3 = new TextField();
private TextField tfGallons3 = new TextField();
private TextField tfMiles4 = new TextField();
private TextField tfGallons4 = new TextField();
private Button calcMPG = new Button("Calculate");
private TextField displayMPG = new TextField();
private RadioButton rbStandard = new RadioButton("Standard");
private RadioButton rbMetric = new RadioButton("Metric");
private Label lblDistance = new Label("Miles:");
private Label lblAmount = new Label("Gallons:");
private Label lblDistance1 = new Label("Miles:");
private Label lblAmount1 = new Label("Gallons:");
private Label lblDistance2 = new Label("Miles:");
private Label lblAmount2 = new Label("Gallons:");
private Label lblDistance3 = new Label("Miles:");
private Label lblAmount3 = new Label("Gallons:");
private Label lblDistance4 = new Label("Miles:");
private Label lblAmount4 = new Label("Gallons:");
private Label lblMPG = new Label("MPG:");
#Override // Override the start method in the Application class
public void start(Stage primaryStage) {
// Create UI
GridPane gridPane = new GridPane();
gridPane.setHgap(5);
gridPane.setVgap(5);
gridPane.add(rbStandard, 0 ,0);
gridPane.add(rbMetric, 1, 0);
gridPane.add(lblDistance, 0, 1);
gridPane.add(tfMiles, 1, 1);
gridPane.add(lblAmount, 0, 2);
gridPane.add(tfGallons, 1, 2);
gridPane.add(lblDistance1, 0, 3);
gridPane.add(tfMiles1, 1, 3);
gridPane.add(lblAmount1, 0, 4);
gridPane.add(tfGallons1, 1, 4);
gridPane.add(lblDistance2, 0, 5);
gridPane.add(tfMiles2, 1, 5);
gridPane.add(lblAmount2, 0, 6);
gridPane.add(tfGallons2, 1, 6);
gridPane.add(lblDistance3, 0, 7);
gridPane.add(tfMiles3, 1, 7);
gridPane.add(lblAmount3, 0, 8);
gridPane.add(tfGallons3, 1, 8);
gridPane.add(lblDistance4, 0, 9);
gridPane.add(tfMiles4, 1, 9);
gridPane.add(lblAmount4, 0, 10);
gridPane.add(tfGallons4, 1, 10);
gridPane.add(calcMPG, 0, 11);
gridPane.add(displayMPG, 1, 12);
gridPane.add(lblMPG, 0, 12);
// Set properties for UI
gridPane.setAlignment(Pos.CENTER);
tfMiles.setAlignment(Pos.BOTTOM_RIGHT);
tfGallons.setAlignment(Pos.BOTTOM_RIGHT);
calcMPG.setAlignment(Pos.BOTTOM_RIGHT);
displayMPG.setAlignment(Pos.BOTTOM_RIGHT);
displayMPG.setEditable(false);
ToggleGroup group = new ToggleGroup();
rbStandard.setToggleGroup(group);
rbMetric.setToggleGroup(group);
// Process events
calcMPG.setOnAction(e -> calculateMPG());
rbStandard.setOnAction(e -> rbStandard());
rbMetric.setOnAction(e -> rbMetric());
// Create a scene and place it in the stage
Scene scene = new Scene(gridPane, 400, 250);
primaryStage.setTitle("MPG Calculator"); // Set title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
rbStandard.setSelected(true);
}
private void calculateMPG() {
double gallons = Double.parseDouble(tfGallons.getText());
double miles = Double.parseDouble(tfMiles.getText());
double mpg = miles / gallons;
displayMPG.setText(String.format("%.2f", mpg));
}
private void rbStandard(){
lblDistance.setText("Miles:");
lblAmount.setText("Gallons:");
lblMPG.setText("MPG:");
double liters = Double.parseDouble(tfGallons.getText());
double kilometers = Double.parseDouble(tfMiles.getText());
double kml = Double.parseDouble(tfMiles.getText());
double gallons = liters / 3.785411784;
double miles = kilometers * 1.6;
double mpg = miles / liters;
tfGallons.setText(String.format("%.2f", gallons));
tfMiles.setText(String.format("%.2f", miles));
displayMPG.setText(String.format("%.2f", mpg));
}
private void rbMetric(){
lblDistance.setText("Kilometers:");
lblAmount.setText("Liters:");
lblMPG.setText("KM/L:");
double gallons = Double.parseDouble(tfGallons.getText());
double miles = Double.parseDouble(tfMiles.getText());
double mpg = Double.parseDouble(tfMiles.getText());
double liters = gallons * 3.785411784;
double kilometers = miles/1.6;
double kml = miles / liters;
tfGallons.setText(String.format("#%.2f", gallons));
tfMiles.setText(String.format("#%.2f", miles));
displayMPG.setText(String.format("#%.2f", mpg));
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
This started out as just a MPG calculator but now I am trying to make it calculate the MPG for up to 5 stops in a trip, and then at the end of the 5 stops, calculate the final MPG for the trip.
Right now it will calculate the MPG for the first stop, but afterwards it leaves out the inputs for the text fields 1-4.
I tried setting the getText in the calculateMPG to the correct text fields but it still didn't change the output. I also thought about just making several methods for each leg but I wasn't sure if there was a more efficient way to do it.
Here is a little bit better of a solution everyone feel free to edit to make more efficient if you want
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class MPGCalc extends Application {
private Button calcMPG = new Button("Calculate");
private TextField displayMPG = new TextField();
private RadioButton rbStandard = new RadioButton("Standard");
private RadioButton rbMetric = new RadioButton("Metric");
private Label[] distanceLabels = new Label[5];
private Label[] amountLabels = new Label[5];
private TextField[] distanceTextFields = new TextField[5];
private TextField[] amountTextFields = new TextField[5];
private Label lblMPG = new Label("MPG:");
#Override // Override the start method in the Application class
public void start(Stage primaryStage) {
createLists();
// Create UI
GridPane gridPane = new GridPane();
gridPane.setHgap(5);
gridPane.setVgap(5);
gridPane.add(rbStandard, 0 ,0);
gridPane.add(rbMetric, 1, 0);
for (int i = 0; i < 10; i++) {
if(i%2==0) {
gridPane.add(distanceLabels[i / 2], 0, i+1);
gridPane.add(distanceTextFields[i / 2], 1, i+1);
}
else {
gridPane.add(amountLabels[i / 2], 0, i+1);
gridPane.add(amountTextFields[i / 2], 1, i+1);
}
}
gridPane.add(calcMPG, 0, 11);
gridPane.add(displayMPG, 1, 12);
gridPane.add(lblMPG, 0, 12);
// Set properties for UI
gridPane.setAlignment(Pos.CENTER);
calcMPG.setAlignment(Pos.BOTTOM_RIGHT);
for (int i = 0; i < distanceLabels.length; i++) {
distanceLabels[i].setAlignment(Pos.BOTTOM_RIGHT);
distanceTextFields[i].setAlignment(Pos.BOTTOM_RIGHT);
}
for (int i = 0; i < amountLabels.length; i++) {
amountLabels[i].setAlignment(Pos.BOTTOM_RIGHT);
amountTextFields[i].setAlignment(Pos.BOTTOM_RIGHT);
}
displayMPG.setAlignment(Pos.BOTTOM_RIGHT);
displayMPG.setEditable(false);
ToggleGroup group = new ToggleGroup();
rbStandard.setToggleGroup(group);
rbMetric.setToggleGroup(group);
// Process events
calcMPG.setOnAction(e -> calculateMPG());
rbStandard.setOnAction(e -> rbStandard());
rbMetric.setOnAction(e -> rbMetric());
// Create a scene and place it in the stage
Scene scene = new Scene(gridPane, 400, 425);
primaryStage.setTitle("MPG Calculator"); // Set title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
rbStandard.setSelected(true);
}
private void createLists(){
for (int i = 0; i < distanceLabels.length; i++) {
distanceLabels[i] = new Label("Miles");
distanceTextFields[i] = new TextField("");
}
for (int i = 0; i < amountLabels.length; i++) {
amountLabels[i] = new Label("Gallons:");
amountTextFields[i] = new TextField("");
}
}
private void setDistanceLabel(String labelName){
for (Label distanceLabel : distanceLabels)
distanceLabel.setText(labelName);
}
private void setAmountLabels(String labelName){
for (Label amountLabel : amountLabels)
amountLabel.setText(labelName);
}
private void calculateMPG() {
double totalTrip = 0;
for (TextField distanceTextField : distanceTextFields)
if (distanceTextField != null && !distanceTextField.getText().equals(""))
totalTrip = totalTrip + Double.parseDouble(distanceTextField.getText());
double totalAmount = 0;
for (TextField amountTextField : amountTextFields) {
if (amountTextField != null && !amountTextField.getText().equals(""))
totalAmount = totalAmount +Double.parseDouble(amountTextField.getText());
}
displayMPG.setText(String.valueOf(totalTrip/totalAmount));
}
private void rbStandard(){
setDistanceLabel("Miles");
setAmountLabels("Gallons:");
lblMPG.setText("MPG:");
}
private void rbMetric(){
setDistanceLabel("Kilometers:");
setAmountLabels("Liters:");
lblMPG.setText("KM/L:");
}
/**
* The main method is only needed for the IDE with limited
* JavaFX support. Not needed for running from the command line.
*/
public static void main(String[] args) {
launch(args);
}
}
I'm writing a javafx image generator for .STL files. I'm using StlMeshImporter to import the STL file. However, when I import files in my javafx scene and try to take a snapshot, I get different result for each file because they are not center in the scene.
I would like to be able to scale it or center it, in the scene dynamically to take a snapshot. Is there a way to get the width and height of the object so I could set a scale factor, and offset automatically?
Here is my class:
public class STLImageGenerator extends Application {
private static final String MESH_FILENAME
= "./9sk02_flex_r02.stl";
private static final int VIEWPORT_SIZE = 800;
private static final double MODEL_SCALE_FACTOR = 3;
private static final double MODEL_X_OFFSET = 0;
private static final double MODEL_Y_OFFSET = 0;
private static final double MODEL_Z_OFFSET =0 ;
// private static final int VIEWPORT_SIZE = 4096;
private static final Color lightColor = Color.rgb(204, 204, 204);
private static final Color jewelColor = Color.rgb(0, 100, 204);
final static int CANVAS_WIDTH = 512;
final static int CANVAS_HEIGHT = 512;
private Group root;
private PointLight pointLight;
Canvas canvas = null;
PerspectiveCamera perspectiveCamera = null;
static MeshView[] loadMeshViews() {
File file = new File(MESH_FILENAME);
StlMeshImporter importer = new StlMeshImporter();
importer.read(file);
Mesh mesh = importer.getImport();
return new MeshView[]{new MeshView(mesh)};
}
private Group buildScene() {
MeshView[] meshViews = loadMeshViews();
System.out.println("MESHVIEWS: " + meshViews.length);
for (int i = 0; i < meshViews.length; i++) {
System.out.println("meshViews[i].getLayoutX():"+meshViews[i].getLayoutX());
meshViews[i].setScaleX(MODEL_SCALE_FACTOR);
meshViews[i].setScaleY(MODEL_SCALE_FACTOR);
meshViews[i].setScaleZ(MODEL_SCALE_FACTOR);
meshViews[i].setTranslateX((VIEWPORT_SIZE / 2) + MODEL_X_OFFSET-MODEL_SCALE_FACTOR);
meshViews[i].setTranslateY((VIEWPORT_SIZE / 2) + MODEL_Y_OFFSET-MODEL_SCALE_FACTOR);
meshViews[i].setTranslateZ((VIEWPORT_SIZE / 2) + MODEL_Z_OFFSET);
PhongMaterial sample = new PhongMaterial(jewelColor);
sample.setSpecularColor(lightColor);
sample.setSpecularPower(16);
meshViews[i].setMaterial(sample);
//meshViews[i].getTransforms().setAll(new Rotate(38, Rotate.Z_AXIS), new Rotate(20, Rotate.X_AXIS));
}
pointLight = new PointLight(lightColor);
pointLight.setTranslateX(VIEWPORT_SIZE * 3 / 4);
pointLight.setTranslateY(VIEWPORT_SIZE / 2);
pointLight.setTranslateZ(VIEWPORT_SIZE / 2);
PointLight pointLight2 = new PointLight(lightColor);
pointLight2.setTranslateX(VIEWPORT_SIZE * 1 / 4);
pointLight2.setTranslateY(VIEWPORT_SIZE * 3 / 4);
pointLight2.setTranslateZ(VIEWPORT_SIZE * 3 / 4);
PointLight pointLight3 = new PointLight(lightColor);
pointLight3.setTranslateX(VIEWPORT_SIZE * 5 / 8);
pointLight3.setTranslateY(VIEWPORT_SIZE / 2);
pointLight3.setTranslateZ(0);
Color ambientColor = Color.rgb(80, 80, 80, 0);
AmbientLight ambient = new AmbientLight(ambientColor);
root = new Group(meshViews);
root.getChildren().add(pointLight);
root.getChildren().add(pointLight2);
root.getChildren().add(pointLight3);
root.getChildren().add(ambient);
//root.setAutoSizeChildren(true);
return root;
}
private PerspectiveCamera addCamera(Scene scene) {
perspectiveCamera = new PerspectiveCamera();
System.out.println("Near Clip: " + perspectiveCamera.getNearClip());
System.out.println("Far Clip: " + perspectiveCamera.getFarClip());
System.out.println("FOV: " + perspectiveCamera.getFieldOfView());
perspectiveCamera.setFieldOfView(5);
scene.setCamera(perspectiveCamera);
return perspectiveCamera;
}
#Override
public void start(Stage primaryStage) {
//canvas = new Canvas(VIEWPORT_SIZE, VIEWPORT_SIZE);
Group group = buildScene();
Scene scene = new Scene(group, VIEWPORT_SIZE, VIEWPORT_SIZE, true, SceneAntialiasing.BALANCED);
scene.setFill(Color.rgb(255, 255, 255));
group.setAutoSizeChildren(true);
addCamera(scene);
//root.getChildren().add(canvas);
primaryStage.setMaxHeight(CANVAS_HEIGHT);
primaryStage.setMaxWidth(CANVAS_WIDTH);
String fname = MESH_FILENAME.substring(0, MESH_FILENAME.length() - 3) + "png";
File file = new File(fname);
primaryStage.setTitle("Jewel Viewer");
primaryStage.setScene(scene);
primaryStage.show();
try {
SnapshotParameters s = new SnapshotParameters();
// s.setCamera(perspectiveCamera);
// s.setViewport(Rectangle2D.EMPTY);
WritableImage wim = new WritableImage(1024, 1024);
scene.snapshot(wim);
// WritableImage writableImage = root.snapshot(new SnapshotParameters(), null);
RenderedImage renderedImage = SwingFXUtils.fromFXImage(wim, null);
ImageIO.write(renderedImage, "png", file);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
System.setProperty("prism.dirtyopts", "false");
Platform.setImplicitExit(false);
launch(args);
}
I am building a Simon Says game in JavaFX. I have gotten most of it working, my only issue now is when you run the game it runs a for loop to generate the colours depending on which level you are on.
It seems to display one colour from the loop but it doesn't wait for the KeyFrame to finish before it flies through the rest of the loop and stores the values. How can I make the loop wait for the KeyFrame to complete so it displays all of the colour changes?
package assign3;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import javafx.animation.FillTransition;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.SequentialTransition;
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.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Question2 extends Application
{
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLUE = 3;
public static final int ORANGE = 4;
private int thisGameScore = 0;
private int level = 1;
private BorderPane obBorder;
private HBox obPane;
private HBox obStart;
private Timeline tlRed;
private Timeline tlBlue;
private Timeline tlGreen;
private Timeline tlOrange;
private SequentialTransition stList = new SequentialTransition();
private Button btStart;
private ArrayList<Integer> colours;
private ArrayList<Integer> guesses;
#Override
public void start( Stage obPrimeStage ) throws Exception
{
boolean runGame = true;
int guessIndex = 0;
obBorder = new BorderPane();
obPane = new HBox();
obStart = new HBox();
Button btRed = new Button("Red");
Button btGreen = new Button("Green");
Button btBlue = new Button("Blue");
Button btOrange = new Button("Orange");
btStart = new Button("Start");
class RedTimeLine
{
Timeline tlRed;
RedTimeLine()
{
tlRed = new Timeline();
tlRed.getKeyFrames().add(new KeyFrame(Duration.ZERO,
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.RED, CornerRadii.EMPTY, Insets.EMPTY)))));
tlRed.getKeyFrames().add(new KeyFrame(Duration.seconds(1),
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)))));
}
}
tlBlue = new Timeline();
tlBlue.getKeyFrames().add(new KeyFrame(Duration.ZERO,
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.BLUE, CornerRadii.EMPTY, Insets.EMPTY)))));
tlBlue.getKeyFrames().add(new KeyFrame(Duration.seconds(1),
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)))));
tlGreen = new Timeline();
tlGreen.getKeyFrames().add(new KeyFrame(Duration.ZERO,
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.GREEN, CornerRadii.EMPTY, Insets.EMPTY)))));
tlGreen.getKeyFrames().add(new KeyFrame(Duration.seconds(1),
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)))));
tlOrange = new Timeline();
tlOrange.getKeyFrames().add(new KeyFrame(Duration.ZERO,
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.ORANGE, CornerRadii.EMPTY, Insets.EMPTY)))));
tlOrange.getKeyFrames().add(new KeyFrame(Duration.seconds(1),
new KeyValue(obBorder.backgroundProperty(),
new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, Insets.EMPTY)))));
obStart.getChildren().add(btStart);
obPane.getChildren().addAll(btRed, btGreen, btBlue, btOrange);
obBorder.setCenter(obPane);
obBorder.setBottom(obStart);
obPane.setAlignment(Pos.CENTER);
obStart.setAlignment(Pos.CENTER);
Scene obScene = new Scene(obBorder, 400, 400);
obPrimeStage.setTitle("Simon Says");
obPrimeStage.setScene(obScene);
obPrimeStage.show();
btStart.setOnAction((ActionEvent start) -> {
colours = new ArrayList<>();
guesses = new ArrayList<>();
obChange.handle(start);
stList.play();
System.out.println("Started new game");
});
btRed.setOnAction((ActionEvent e) ->
{
guesses.add(RED);
if(guesses.get(guessIndex) != colours.get(guessIndex) )
{
obStart.getChildren().add(btStart);
level = 1;
}
else
{
if(guesses.size() == colours.size())
{
level += 1;
colours = new ArrayList<>();
guesses = new ArrayList<>();
for(int i = 0; i < level; i++)
{
obChange.handle(e);
}
stList.play();
}
}
});
btGreen.setOnAction((ActionEvent e) ->
{
guesses.add(GREEN);
if(guesses.get(guessIndex) != colours.get(guessIndex) )
{
obStart.getChildren().add(btStart);
level = 1;
}
else
{
if(guesses.size() == colours.size())
{
level += 1;
colours = new ArrayList<>();
guesses = new ArrayList<>();
for(int i = 0; i < level; i++)
{
obChange.handle(e);
}
stList.play();
}
}
});
btBlue.setOnAction((ActionEvent e) ->
{
guesses.add(BLUE);
if(guesses.get(guessIndex) != colours.get(guessIndex) )
{
obStart.getChildren().add(btStart);
level = 1;
}
else
{
if(guesses.size() == colours.size())
{
level += 1;
colours = new ArrayList<>();
guesses = new ArrayList<>();
for(int i = 0; i < level; i++)
{
obChange.handle(e);
}
stList.play();
}
}
});
btOrange.setOnAction((ActionEvent e) ->
{
guesses.add(ORANGE);
if(guesses.get(guessIndex) != colours.get(guessIndex) )
{
obStart.getChildren().add(btStart);
level = 1;
}
else
{
if(guesses.size() == colours.size())
{
level += 1;
guesses = new ArrayList<>();
for(int i = 0; i < level; i++)
{
obChange.handle(e);
}
stList.play();
}
}
});
}
class ChangeColour implements EventHandler<ActionEvent>
{
#Override
public void handle( ActionEvent arg0 )
{
thisGameScore = 0;
int randomColour = (int)((Math.random() * 4) + 1);
if(randomColour == RED)
{
colours.add(RED);
stList.getChildren().add(new RedTimeLine());
}
else if(randomColour == BLUE)
{
colours.add(BLUE);
stList.getChildren().add(tlBlue);
}
else if(randomColour == GREEN)
{
colours.add(GREEN);
stList.getChildren().add(tlGreen);
}
else if(randomColour == ORANGE)
{
colours.add(ORANGE);
stList.getChildren().add(tlOrange);
}
obStart.getChildren().remove(btStart);
}
}
ChangeColour obChange = new ChangeColour();
public static void main( String[] args )
{
Application.launch(args);
}
}
I guess I would do something like this:
public void playSequence(int sequenceLength, double speed) {
Timeline timeline = new Timeline();
for (int i = 0; i < sequenceLength; i++) {
Color color = colors[random.nextInt(colors.length)];
Segment segment = segmentMap.get(color);
timeline.getKeyFrames().addAll(
new KeyFrame(
Duration.seconds(i), new KeyValue(segment.litProperty(), true)
),
new KeyFrame(
Duration.seconds(i + 0.9), new KeyValue(segment.litProperty(), false)
)
);
isPlaying.set(true);
timeline.setOnFinished(event -> isPlaying.set(false));
timeline.setRate(speed);
timeline.play();
}
}
The above example uses a Timeline, with the start time at which each segment is lit varying to light each segment in sequence.
Full sample
import javafx.animation.*;
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.*;
import javafx.scene.control.Button;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import static javafx.scene.paint.Color.*;
public class SimpleSimon extends Application {
private int sequenceLength = 1;
private int speed = 1;
#Override
public void start(Stage stage) throws Exception {
Simon simon = new Simon();
Button play = new Button("Play");
play.setStyle("-fx-font-size: 20px;");
play.disableProperty().bind(simon.isPlayingProperty());
play.setOnAction(event -> {
simon.playSequence(sequenceLength, speed);
sequenceLength++;
speed *= 1.05;
});
VBox layout = new VBox(10, simon, play);
layout.setPadding(new Insets(10));
layout.setAlignment(Pos.CENTER);
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
class Simon extends Group {
private static final Random random = new Random(42);
private final Color[] colors = {
RED, GREEN, BLUE, ORANGE
};
private Map<Color, Segment> segmentMap = new HashMap<>();
private ReadOnlyBooleanWrapper isPlaying = new ReadOnlyBooleanWrapper();
public Simon() {
for (int i = 0; i < colors.length; i++) {
Segment segment = new Segment(colors[i], i * 90);
getChildren().add(segment);
segmentMap.put(colors[i], segment);
}
}
public void playSequence(int sequenceLength, double speed) {
Timeline timeline = new Timeline();
for (int i = 0; i < sequenceLength; i++) {
Color color = colors[random.nextInt(colors.length)];
Segment segment = segmentMap.get(color);
timeline.getKeyFrames().addAll(
new KeyFrame(
Duration.seconds(i), new KeyValue(segment.litProperty(), true)
),
new KeyFrame(
Duration.seconds(i + 0.9), new KeyValue(segment.litProperty(), false)
)
);
}
isPlaying.set(true);
timeline.setOnFinished(event -> isPlaying.set(false));
timeline.setRate(speed);
timeline.play();
}
public boolean isPlaying() {
return isPlaying.get();
}
public ReadOnlyBooleanWrapper isPlayingProperty() {
return isPlaying;
}
}
class Segment extends Arc {
private BooleanProperty lit = new SimpleBooleanProperty();
private static final double RADIUS = 100;
private static final ColorAdjust litEffect = new ColorAdjust(0, 0, 0.5, 0);
private static final ColorAdjust unlitEffect = new ColorAdjust(0, 0, 0, 0);
public Segment(Color color, double angleOffset) {
super(RADIUS, RADIUS, RADIUS, RADIUS, angleOffset, 90);
setFill(color);
setType(ArcType.ROUND);
setEffect(unlitEffect);
lit.addListener((observable, oldValue, newValue) ->
setEffect(lit.get() ? litEffect : unlitEffect)
);
}
public void setLit(boolean lit) {
this.lit.set(lit);
}
public boolean isLit() {
return lit.get();
}
public BooleanProperty litProperty() {
return lit;
}
}
A similar effect could be achieved via a SequentialTransition.
I am trying to use two for loops to automatically add ImageView nodes to each location. When using the for loops I receive an error. When I comment the for loop code out with only one statement to add an ImageView node the code seems to work can you use for loops to populate GridPane? If so what am I doing wrong? If not what could be used as a solution?
My Class:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class GridCreation extends Application {
#Override
public void start(Stage gameStage) throws Exception {
GridPane grid = new GridPane();
Image backOfCardsImg = new Image("images/naruto_shipuden_logo.png");
ImageView backOfCards = new ImageView(backOfCardsImg);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
grid.add(backOfCards, i, j);
}
}
//grid.add(backOfCards, 1,1);
Scene scene = new Scene(grid);
gameStage.setTitle("MemoryGame");
gameStage.setScene(scene);
gameStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Edit: for the code:
grid.add(backOfCards, i, j);
I changed the line of code to
grid.add(new ImageView(backOfCardImg), i, j);
this seemed to solve the problem but can anyone explain to me why the first option wouldnt work?
This might be a usable start for a memory game in fx. It uses an own extension of ImageView to do the turn and focus animations and to deal with a common backside image. Its only graphics, no game logic.
public class MemoryGame extends Application {
final int rows = 4;
final int columns = 4;
CardView views[][] = new CardView[rows][];
public static class CardView extends ImageView {
static final double scale = 0.95;
static DropShadow shadowhoover = new DropShadow(5, 4, 4, Color.rgb(50, 60, 50));
static DropShadow shadowdown = new DropShadow(2, 2, 2, Color.rgb(50, 60, 50));
static Image backside = null;
public static void setbackside(Image image) { backside = image; }
public CardView(Image image) {
super(backside);
setRotationAxis(new Point3D(0, 200,0));
setScaleX(scale);
setScaleY(scale);
setEffect(shadowdown);
setOnMouseEntered(m -> {
setEffect(shadowhoover);
setScaleX(scale*1.01);
setScaleY(scale*1.01);
});
setOnMouseExited(m -> {
setEffect(shadowdown);
setScaleX(scale);
setScaleY(scale);
});
setOnMouseClicked(m -> {
RotateTransition r1 = new RotateTransition(Duration.millis(300), this);
r1.setByAngle(90);
r1.setOnFinished(e -> setImage(image));
RotateTransition r2 = new RotateTransition(Duration.millis(300), this);
r2.setByAngle(-90);
RotateTransition r3 = new RotateTransition(Duration.millis(300), this);
r3.setByAngle(90);
r3.setOnFinished(e -> setImage(backside));
RotateTransition r4 = new RotateTransition(Duration.millis(300), this);
r4.setByAngle(-90);
new SequentialTransition(r1, r2, new PauseTransition(Duration.millis(1000)), r3, r4).play();
});
}
}
#Override
public void start(Stage gameStage) throws Exception {
GridPane grid = new GridPane();
grid.setBackground(new Background(new BackgroundFill(Color.rgb(140, 200, 140), new CornerRadii(0), new Insets(0))));
grid.setHgap(5);
grid.setVgap(5);
Image back = new Image(MemoryGame.class.getResource("card-back.png").toExternalForm(), 140, 200, true, true);
Image front = new Image(MemoryGame.class.getResource("card-1.png").toExternalForm(), 140, 200, true, true);
CardView.setbackside(back);
for (int r = 0; r < rows; r++) {
views[r] = new CardView[columns];
for (int c = 0; c < columns; c++) {
CardView view = new CardView(front); // different front images of course...
views[r][c] = view;
HBox box = new HBox(5);
box.getChildren().add(views[r][c]);
grid.add(box, c, r);
}
}
//grid.add(backOfCards, 1,1);
Scene scene = new Scene(grid);
gameStage.setTitle("MemoryGame");
gameStage.setScene(scene);
gameStage.show();
}
public static void main(String[] args) {
launch(args);
}
}