Change a circle to a square to fill a square in JavaFX - animation

I found an amazing animation in which there is transition from circle/ellipse to square and just before the end of the animation, the square protrudes out a little and then adjusts itself it back to the correct size.
Source: https://clementmihailescu.github.io/Pathfinding-Visualizer/#
I tried to recreate it but I am not able to get the transition effect from a drop of ink to square.
package sample;
import javafx.animation.*;
import javafx.application.Application;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.Lighting;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import javafx.util.Duration;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Rectangle originalRectangle = new Rectangle(100,100);
originalRectangle.setFill(Color.WHITE);
originalRectangle.setStroke(Color.BLUE);
Rectangle substituteRectangle = new Rectangle(25,25,50,50);
substituteRectangle.setOpacity(0.0);
substituteRectangle.setFill(Color.TURQUOISE);
substituteRectangle.setStroke(Color.TURQUOISE);
Rectangle yellowRectangle = new Rectangle(100,100);
yellowRectangle.setFill(Color.YELLOW);
root.getChildren().addAll(originalRectangle,substituteRectangle,yellowRectangle);
FadeTransition fadeOutTransition = new FadeTransition(Duration.millis(3000),yellowRectangle); //Make the duration as 1ms to get the instant
fadeOutTransition.setFromValue(1.0);
fadeOutTransition.setToValue(0.0);
FadeTransition fadeInTransition = new FadeTransition(Duration.millis(1),substituteRectangle);
fadeInTransition.setFromValue(0.0);
fadeInTransition.setToValue(0.8);
//To make the square protrute out a bit
ScaleTransition scaleTransition = new ScaleTransition(Duration.seconds(4),substituteRectangle);
scaleTransition.setToX(2.1);
scaleTransition.setToY(2.1);
ParallelTransition parallelTransition = new ParallelTransition(scaleTransition,fadeInTransition);
fadeOutTransition.play();
fadeOutTransition.setOnFinished(e -> {
parallelTransition.setOnFinished(event -> {
root.getChildren().removeAll(substituteRectangle,yellowRectangle);
originalRectangle.setOpacity(1.0);
originalRectangle.setFill(Color.RED);
});
parallelTransition.play();
});
Scene scene = new Scene(root,800,600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}

The probably simplest way of achieving this kind of animation would be to simply animate the radius of the circle and constrain it's size using a Rectangle as clip. Also often Timeline provides a animation that is well suited to replace multiple transitions. In this case the fact that it allows for animations between colors as well as animations for a DoubleProperty makes this a good choice for simplifying the animations:
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
Rectangle bounds = new Rectangle(50, 50, 100, 100);
Circle circle = new Circle(bounds.getX() + 0.5 * bounds.getWidth(), bounds.getY() + 0.5 * bounds.getHeight(),
0);
circle.setClip(bounds);
root.getChildren().add(circle);
Timeline animation = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(circle.fillProperty(), Color.BLUE),
new KeyValue(circle.radiusProperty(), 0d)),
new KeyFrame(Duration.seconds(5), new KeyValue(circle.fillProperty(), Color.RED), new KeyValue(
circle.radiusProperty(), 0.5 * Math.hypot(bounds.getWidth(), bounds.getHeight())))); // at the end of the animation the circle should reach the corners -> diameter = diagonale of rect
root.setOnMouseClicked(evt -> animation.playFromStart());
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}

Related

TableView columns position and TabbedPane tabs start from Right Side instead of left in JavaFX?

i've been searching for hours and could not find any way to make the tableView columns and tabs of a TabbedPane start from the right side instead of left.
As we can see in the picture java by default create them from the left side to the right, and leave empty space on the right side. Is there any way to do this vice versa ?
Thank you
see image here
Use setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
import javafx.application.Application;
import javafx.geometry.NodeOrientation;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
public class NodeOrientationTest extends Application {
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
Tab tab1 = new Tab("Tab 1");
Tab tab2 = new Tab("Tab 2");
tabPane.getTabs().addAll(tab1, tab2);
TableView<Void> table = new TableView<>();
table.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT);
table.getColumns().add(new TableColumn<Void, Void>("Column 1"));
table.getColumns().add(new TableColumn<Void, Void>("Column 2"));
tab1.setContent(table);
Scene scene = new Scene(tabPane, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Note that the table view will, by default, inherit this from its parent, so you can omit the call to table.setNodeOrientation(NodeOrientation.RIGHT_TO_LEFT); and achieve the same result. (Or just set it on the scene.)

Javafx GUI programming

So im trying to make 3 buttons on the top panel and 3 radio buttons on the bottom panel, but when i run it, it comes out all weird, would love it if someone can help me. Im still pretty new to GUI so my code might be completely wrong.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
public class ColorFactory extends Application {
#Override
public void start(Stage stage)
{
BorderPane pane = new BorderPane();
// sets the width and height
stage.setHeight(300);
stage.setWidth(500);
//calls the mainpanel constructor
pane.setCenter(new MainPanel());
//make the mainpanel visible using the setVisible(true)
//call the stage.setScene
stage.setScene(new Scene(pane));
// set title to Color Factory
stage.setTitle("Color Factory");
//call stage.show
stage.show();
}
private class MainPanel extends BorderPane
{
public MainPanel()
{
HBox Tpanel = new HBox(25);
Tpanel = new HBox(25);
Tpanel.setPrefWidth(500);
Tpanel.setPrefHeight(50);
Tpanel.setAlignment(Pos.TOP_CENTER);
Button red = new Button("Red");
red.setStyle("-fx-background-color: red");
Button yellow = new Button("Yellow");
yellow.setStyle("-fx-background-color: yellow;");
Button orange = new Button("Orange");
orange.setStyle("-fx-background-color: orange;");
Tpanel.setStyle("-fx-background-color: white;");
Tpanel.getChildren().addAll(red,yellow,orange);
HBox Bpanel = new HBox(15);
Bpanel.setPrefWidth(500);
Bpanel.setPrefHeight(75);
RadioButton green = new RadioButton("Green");
RadioButton blue = new RadioButton("Blue");
RadioButton cyan = new RadioButton("Cyan");
green.setStyle("-fx-background-color: green;");
blue.setStyle("-fx-background-color: blue;");
cyan.setStyle("-fx-background-color: cyan;");
Bpanel.setAlignment(Pos.BOTTOM_CENTER);
Bpanel.getChildren().addAll(green,blue,cyan);
Label label = new Label("Top buttons change the panel color and bottom radio buttons change the text color");
label.setAlignment(Pos.CENTER_LEFT);
label.setTextFill(Color.BLUE);
getChildren().addAll(Tpanel,Bpanel,label);
HBox.setMargin(Tpanel, new Insets(5,10,5,10));
HBox.setMargin(Bpanel, new Insets(5,10,5,10));
HBox.setMargin(label, new Insets(150,10,5,10));
}
}
public static void main(String[] args) {
launch(args);
}
}
Your MainPanel is a BorderPane: simply adding nodes to it will put them all in the top left by default (so they are all on top of each other). When using a BorderPane, you need to call setCenter(...), setTop(...), setLeft(...) etc to position the nodes.
E.g.:
// getChildren().addAll(Tpanel,Bpanel,label);
setTop(Tpanel);
setBottom(Bpanel);
setCenter(label);

How to model a bending straw in JavaFX

My goal is to make it so that when a user slides a Slider, an object that is like a straw bends from its middle.
Sort of like this:
http://s.hswstatic.com/gif/bendy-straw-a-1.jpg
I've spent days searching for ways to model this with JavaFX shapes, but maybe I'm missing something obvious. When the Slider is at zero, the shape should be a straight line, whereas when the Slider is bent all the way, the shape should resemble an arm of a hyperbola.
Thank you so much.
You'll have to figure out the math correctly, but something like this is what I had in mind. You can even try just leaving the control point Y in the middle of the line, I moved it up since I figured it's more realistic, like it will start to bend at the bottom. You also have to do some calculus to figure out the end point. The length shouldn't change.
package curve;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Slider;
import javafx.scene.paint.Color;
import javafx.scene.shape.QuadCurve;
import javafx.stage.Stage;
public class Curve extends Application {
#Override
public void start(Stage primaryStage) {
QuadCurve qc = new QuadCurve(100, 500, 100, 250, 100, 0);
qc.setStroke(Color.BLUE);
qc.setStrokeWidth(5);
qc.setFill(Color.TRANSPARENT);
Slider slider = new Slider(0, 200, 0);
qc.endXProperty().bind(slider.valueProperty().add(100));
qc.endYProperty().bind(slider.valueProperty().add(100).divide(1.2));
qc.controlYProperty().bind(slider.valueProperty().multiply(-1).add(500));
Group group = new Group(qc,slider);
Scene scene = new Scene(group, 500,500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

When Loading Image Using BufferdImage and ImageIO it Clears my Whole Frame and Does Not Display Image

I and making a program using basic GUI involving buttons, frames, and panels, and everything was fine until I tried to load an image from my project folder. When i add the line of code
try{
titleImage = ImageIO.read(new File("mouse_title_resize.png"));
}
catch(Exception e){}
After I run the program my whole frame just becomes blank whereas before I had some JButtons on it.All the code I had before the try-catch line worked perfectly fine and I tested to see that the only thing that breaks it is this line of code. I receive no errors or anything and I have the image in my project folder and it seems that the image loaded fine, except it wont show up on the frame, and everything else on the frame disappears. I just don't understand why it clears my whole frame when i load the image.
Here is the full code:
This is the class that extends JFrame
package mouse.click.game;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class MouseClickGame extends JFrame {
//Constants to define the frame width and height including borders
public final int FRAME_WIDTH = 600;
public final int FRAME_HEIGHT = 600;
//Dimension from Toolkit to be able to get width and height of screen
public Dimension sizeTool = Toolkit.getDefaultToolkit().getScreenSize();
//Using sizeTool to get width of screen
public double xResolution = sizeTool.getWidth();
//Using sizeTool to get height of screen
public double yResolution = sizeTool.getHeight();
//Creating a point object that is defined as the center of the screen
public Point middleOfScreen = new Point((int) (xResolution / 2) - (FRAME_WIDTH / 2), (int) (yResolution / 2) - (FRAME_HEIGHT / 2));
public MouseClickGame() {
super("WELCOME :D");
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLocation(middleOfScreen);
add(new MouseClickPanel());
}
public static void main(String[] args) {
//Calling constructor
MouseClickGame mainClickGame = new MouseClickGame();
}
}
And here is the class that extends JPanel (these are the only two classes in my project)
package mouse.click.game;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class MouseClickPanel extends JPanel {
JButton buttonPlay = new JButton("Play");
JButton buttonContinue = new JButton("Continue");
JButton buttonOptions = new JButton("Options");
JButton buttonExit = new JButton("Exit");
BoxLayout boxLay = new BoxLayout(this, BoxLayout.Y_AXIS);
Dimension menuButtonSize = new Dimension(300, 30);
Dimension spacingBetweenButtons = new Dimension(0, 30);
BufferedImage titleImage;
public MouseClickPanel() {
try {
titleImage = ImageIO.read(new File("C:\\Users\\Justin\\Desktop\\mouse_title.png"));
} catch (IOException e) {
}
setLayout(boxLay);
add(Box.createVerticalGlue());
add(new JLabel(new ImageIcon(titleImage)));
//Adding glue to force buttons away from top of panel
add(Box.createVerticalGlue());
add(buttonPlay);
//Vertical spacing between buttons
add(Box.createRigidArea(spacingBetweenButtons));
add(buttonContinue);
add(Box.createRigidArea(spacingBetweenButtons));
add(buttonOptions);
add(Box.createRigidArea(spacingBetweenButtons));
add(buttonExit);
//Adding glue to force buttons away from bottom of panel
add(Box.createVerticalGlue());
//Aligning all buttons to centered horizontally
buttonPlay.setAlignmentX(Box.CENTER_ALIGNMENT);
buttonContinue.setAlignmentX(Box.CENTER_ALIGNMENT);
buttonOptions.setAlignmentX(Box.CENTER_ALIGNMENT);
buttonExit.setAlignmentX(Box.CENTER_ALIGNMENT);
//Setting button sizes
buttonPlay.setMaximumSize(menuButtonSize);
buttonContinue.setMaximumSize(menuButtonSize);
buttonOptions.setMaximumSize(menuButtonSize);
buttonExit.setMaximumSize(menuButtonSize);
}
}
Literally if i get ride of the titleImage = and add(new JLabel) lines everything goes back to normal
My guess is that you've just got the path wrong -- a common mistake. In that case, you should be getting an exception like:
Exception in thread "main" javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(ImageIO.java:1301)
at jonathanrmiproject.MyProject.main(JonathanRmiProject.java:24)
This simple example works for me:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.naming.NamingException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class MyProject {
public static void main(String[] args) throws NamingException, IOException {
BufferedImage img = ImageIO.read(new File("myimage.jpg"));
JLabel label = new JLabel(new ImageIcon(img));
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(label);
f.pack();
f.setLocation(200, 200);
f.setVisible(true);
}
}
I am using Netbeans IDE, and I have saved the image file to "C:\Users\David.Sharpe\MyProject\myimage.jpg".
I should add that if this is not the case, and you do have the correct path, then you need to post a more detailed question so that someone can help you. Include the code to reproduce the problem.
UPDATE: Wow literally the reason it wasn't showing up was because i called setVisble(true) too early. I can't believe it was something that simple. I guess that explains why one time everything would show up and it would be fine but then every time after nothing showed up.
So in my constructor I had
public class MouseClickGame extends JFrame {
public MouseClickGame() {
super("WELCOME :D");
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocation(middleOfScreen);
setVisible(true);
add(new MouseClickPanel());
}
public static void main(String[] args) {
//Calling constructor
MouseClickGame mainClickGame = new MouseClickGame();
}
}
when all I had to do was put the setVisble() after the add(newMouseClickPanel())
Thank you DavidS for your suggestions :D

JavaFX Canvas Rendering Performance

I work on a JavaFX application and have to draw a lot (4000) of arc's.
I'm using the JavaFX Canvas method strokeArc of the graphic context.
The application performs very weak, but not the calls of the methods strokeArc, I think the delay occurs later, maybe at the rendering.
The results is, that the application does take a delay about 5 seconds to show the arc's on the gui.
Is there a faster way to draw the arc's in JavaFX?
No, there isn't. Canvas is the fastest.
You didn't provide a MCVE. I just tried a simple application. Works pretty fast, 4000 arcs drawn in 6ms. The application window shows up immediately. Here's the code:
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
public class ArcTest extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Group root = new Group();
Canvas canvas = new Canvas(300, 250);
GraphicsContext gc = canvas.getGraphicsContext2D();
root.getChildren().add(canvas);
primaryStage.setScene(new Scene(root));
primaryStage.show();
drawShapes(gc);
}
private void drawShapes(GraphicsContext gc) {
long time = System.currentTimeMillis();
gc.setFill(Color.GREEN);
gc.setStroke(Color.BLUE);
gc.setLineWidth(5);
for( int i=0; i < 4000; i++) {
gc.strokeArc(10, 160, 30, 30, 45, 240, ArcType.OPEN);
}
System.out.println( System.currentTimeMillis() - time);
}
}
Unless you provide some code with more information (BlendMode, etc) it's hard to help you.

Resources