java fx gridpane setpadding - javafx

I am trying to set the padding for my GridPane, but every time I set the padding it gives me the error message:
incompatible types: java.awt.Insets cannot be converted to javafx.geometry.insets
Every website I go to and every search states to implement it like this:
grid.setPadding(new Insets(10, 10, 10, 10));
And in my code I have it set exactly the same just for testing purposes :
grid.setPadding(new Insets(10, 10, 10, 10));
So I don't understand why it won't allow me to write that, I have also tried to research the error message but nothing comes up.
Here is my code:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package myrectangle2d;
import java.awt.Insets;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
/**
*
* #author macuser
*/
public class Exercise18_29 extends Application {
Stage window;
Label label1, label2, centerXL, centerXR;
TextField textCenterXL, textCenterXR;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
window = primaryStage;
window.setTitle("Triangles");
GridPane grid = new GridPane();
grid.setPadding(new Insets(10, 10, 10, 10));
label1 = new Label("Do the Triangles match");
GridPane.setConstraints(label1, 0, 0);
label2 = new Label("Yes or no");
GridPane.setConstraints(label2, 1, 0);
centerXL = new Label("Center X LEFT");
GridPane.setConstraints(centerXL, 0, 5);
textCenterXL = new TextField();
GridPane.setConstraints(textCenterXL, 1, 5);
centerXR = new Label("Center X RIGHT");
GridPane.setConstraints(centerXL, 0, 5);
textCenterXR = new TextField();
GridPane.setConstraints(textCenterXR, 3, 5);
grid.getChildren().addAll(label1, label2, centerXL, textCenterXL, centerXR, textCenterXR);
Scene scene = new Scene(grid, 400, 600);
window.setScene(scene);
window.show();
}
}

The error message tells you everything you need to know:
incompatible types: java.awt.Insets cannot be converted to javafx.geometry.insets
You have imported java.awt.Insets: (first import line in your code) you need javafx.geometry.Insets.

The answer above is good. You need
import javafx.geometry.Insets;
instead of
import java.awt.Insets;
I generated the error first time when I allowed my IDE to auto import the necessary libraries. Sometimes the shortcuts bite.

Related

Duplicate the view of a component in javafx

I am looking for a way to duplicate just the view of a component in javafx. This duplicate will not have any of the mouse or key events, and will basically be like a canvas.
As long as this duplicate doesn't change, I can use the snapshot(...) method that nodes have. My problem is that I want this to be dynamic. For example, I have one pane which displays some sort of animation (which can depend on user input), and I want a second pane which show the exact same image (but cannot have in itself user input like mouse presses).
The reflection effect is very specific case of what I need. Is there any way to do it in general?
One way to do it (which I used so far) is to just create a second duplicate component and connect all its input to the first. The problem is that this is a lot of work for every component that I want to copy, and it cannot be done generically.
A second way is just to take a snapshot every time the original component changes and copy it to the duplicate. This should be the solution, but I think that there is supposed to be a more low level solution instead of listening to changes, create an Image duplicate and then update an ImageView.
You could use some kind of binding. This is a basic example
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.Separator;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
*
* #author blj0011
*/
public class JavaFXTestingGround extends Application
{
/**
* #param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
Circle circle = new Circle(0, 200, 25, Color.BLUE);
Circle duplicateCircle = new Circle(25, Color.BLUE);
#Override
public void start(Stage primaryStage)
{
duplicateCircle.centerXProperty().bind(circle.centerXProperty());
duplicateCircle.centerYProperty().bind(circle.centerYProperty());
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1.0 / 40.0), (ActionEvent t) -> {
circle.setCenterX(circle.getCenterX() + 1);
}));
timeline.setCycleCount(Timeline.INDEFINITE);
circle.setOnMouseClicked((t) -> {
switch (timeline.getStatus()) {
case STOPPED:
timeline.play();
break;
case RUNNING:
timeline.stop();
break;
}
});
Pane root = new Pane(circle);
primaryStage.setTitle("Test");
primaryStage.setScene(new Scene(root, 400, 400));
primaryStage.show();
Pane duplicateRoot = new Pane(duplicateCircle);
Stage duplicatStage = new Stage();
duplicatStage.setScene(new Scene(duplicateRoot, 400, 400));
duplicatStage.setX(primaryStage.getX() + primaryStage.getWidth() + 10);
duplicatStage.setY(primaryStage.getY());
duplicatStage.show();
}
}

How to add a CSS-File to a JavaFX Scene without FXML?

I need to add a CSS-file to the Main Scene. It's a first year JavaFX project and we can't use FXML, so this is the only way I know how to navigate between different forms, any other suggestions as on how to switch between JavaFX classes would be appreciated.
package javalearningcurve;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
/**
*
* #author Conor
*/
public class MainMenu extends Stage {
GridPane grid = new GridPane();
Text scenetitle = new Text("Main Menu");
Button btnQuiz = new Button("New Quiz");
Button btnViewResults = new Button("View Results");
Button btnLogout = new Button("Logout");
Button btnQuit = new Button("Quit");
HBox hbBtn = new HBox();
MainMenu() {
this.setTitle("Main Menu");
grid.setAlignment(Pos.TOP_CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(10,25,25,25));
scenetitle.setFont(Font.font("Tahoma", FontWeight.BOLD, 20));
scenetitle.setFill(Color.RED);
grid.setHalignment(scenetitle, HPos.CENTER);
hbBtn.setPrefWidth(200);
hbBtn.setAlignment(Pos.CENTER);
btnQuiz.setMinWidth(hbBtn.getPrefWidth());
btnViewResults.setMinWidth(hbBtn.getPrefWidth());
btnLogout.setMinWidth(hbBtn.getPrefWidth());
btnQuit.setMinWidth(hbBtn.getPrefWidth());
grid.add(scenetitle, 0, 2, 2, 1);
grid.add(btnQuiz, 0, 3);
grid.add(btnViewResults,0 , 4);
grid.add(btnLogout,0 , 5);
grid.add(btnQuit,0 , 6);
//primaryStage.show();
this.setScene(new Scene(grid, 400, 275));
this.show();
}
}
scene.getStylesheets().add(getClass().getResource("/stylesheet.css").toExternalForm());
So basically, instead of this.setScene(new Scene(grid, 400, 275)); do this:
Scene scene = new Scene(grid, 400, 275);
scene.getStylesheets().add(this.getClass().getResource("/stylesheet.css").toExternalForm());
this.setScene(scene);

Animate splitpane divider

I have a horizontal split pane, and i would like to on button click, change divider position, so that i create sort of "slide" animation.
divider would start at 0 (complete left) and on my click it would open till 0.2, when i click again, it would go back to 0;
now i achived this, i just use
spane.setdividerPositions(0.2);
and divider position changes, but i cant manage to do this slowly i would really like that slide feeling when changing divider position.
Could anyone help me ? all examples i found on google, show some DoubleTransition, but that does not exist anymore in java 8, at least i dont have import for that.
You can call getDividers().get(0) to get the first divider. It has a positionProperty() that you can animate using a timeline:
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.util.Duration;
public class AnimatedSplitPane extends Application {
#Override
public void start(Stage primaryStage) {
SplitPane splitPane = new SplitPane(new Pane(), new Pane());
splitPane.setDividerPositions(0);
BooleanProperty collapsed = new SimpleBooleanProperty();
collapsed.bind(splitPane.getDividers().get(0).positionProperty().isEqualTo(0, 0.01));
Button button = new Button();
button.textProperty().bind(Bindings.when(collapsed).then("Expand").otherwise("Collapse"));
button.setOnAction(e -> {
double target = collapsed.get() ? 0.2 : 0.0 ;
KeyValue keyValue = new KeyValue(splitPane.getDividers().get(0).positionProperty(), target);
Timeline timeline = new Timeline(new KeyFrame(Duration.millis(500), keyValue));
timeline.play();
});
HBox controls = new HBox(button);
controls.setAlignment(Pos.CENTER);
controls.setPadding(new Insets(5));
BorderPane root = new BorderPane(splitPane);
root.setBottom(controls);
Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

Set a shape drawn on another shape as Invisible

I want to draw a line passing through a circle. However, I do not want the line to be shown while its inside the circle. How can I accomplish this? Note that I'm drawing the circle first and then the line.
I used a couple of things like:
Circle.setOpacity to 1, which didn't help!
Used line.toBack() after adding the circle and line in the same group. This didnt help either
line.toBack()
line.toFront()
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
public class LineUnderCircle extends Application {
#Override
public void start(Stage stage) throws Exception {
Line line = new Line(10, 10, 50, 50);
line.setStrokeWidth(3);
Circle left = new Circle(10, 10, 8, Color.FORESTGREEN);
Circle right = new Circle(50, 50, 8, Color.FIREBRICK);
Button lineToBack = new Button("Line to back");
lineToBack.setOnAction(e -> line.toBack());
Button lineToFront = new Button("Line to front");
lineToFront.setOnAction(e -> line.toFront());
Pane shapePane = new Pane(line, left, right);
HBox controlPane = new HBox(10, lineToBack, lineToFront);
VBox layout = new VBox( 10, controlPane, shapePane);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}

How can a dynamically generated JavaFX scene be changed in a single stage?

I'm currently working on a project requiring me to switch back and forward between scenes. I have already written some code for it but it isn't as elegant as I wanted to be, especially as there is few flickers when I switch between them and sometimes even the buttons that I have generated simply disappear only to appear once again when yet another scene has been generated. Moreover, the layout I'm using for my application isn't really fixed and I think that using FXML might be not suitable for what I'm doing.
Thank you.
This is what I'm using to change between scenes:
void changeScene(Stage stage,Scene scene){
stage.setScene(scene);
primaryStage.setFullScreen(true);
}
I assume by "switching between scenes" you mean that you want to change the entire content of the existing window.
There are two (very) slightly different ways you can do this. Either create a new Scene and pass it to the Stage's setScene(...) method. Or create the Parent that is the root of the new UI (either by FXML or otherwise), and pass it to the existing Scene's setRoot(...) method. There's no real advantage that I can see of one over the other.
Here's a minimal implementation of the second option. The UI is irrelevant to the question: the important parts are the event handlers for the "Login" button (which switches from the login scene to the main scene) and the "Logout" button (which switches back).
import java.util.stream.IntStream;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class MinimalSceneSwitchingExample extends Application {
#Override
public void start(Stage primaryStage) {
LoginView loginView = new LoginView();
Scene scene = new Scene(loginView.getView(), 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class LoginView {
private final IntegerProperty loginAttempts ;
private final GridPane view ;
public LoginView() {
view = new GridPane();
TextField usernameTF = new TextField("user");
TextField passwordTF = new TextField("pass");
// Login button switches to main view:
Button loginButton = new Button("Login");
loginButton.setOnAction(event -> {
if (usernameTF.getText().equalsIgnoreCase("user")
&& passwordTF.getText().equalsIgnoreCase("pass")) {
// *** Switch to main view: ***
Parent mainView = new MainView().getView();
view.getScene().setRoot(mainView);
} else {
loginAttempts.set(loginAttempts.get()+1);
}
});
// just set up login UI... irrelevant to this example:
loginAttempts = new SimpleIntegerProperty();
usernameTF.setPromptText("Hint: user");
passwordTF.setPromptText("Hint: pass");
view.addRow(0, new Label("Username:"), usernameTF);
view.addRow(1, new Label("Password:"), passwordTF);
Label loginErrorMessage = new Label();
loginErrorMessage.textProperty().bind(
Bindings.when(loginAttempts.isEqualTo(0))
.then("")
.otherwise(Bindings.format("Login incorrect (Attempts: %d)",
loginAttempts)));
view.add(loginErrorMessage, 0, 2, 2, 1);
view.add(loginButton, 0, 3, 2, 1);
ColumnConstraints leftCol = new ColumnConstraints();
leftCol.setHgrow(Priority.NEVER);
leftCol.setHalignment(HPos.RIGHT);
ColumnConstraints rightCol = new ColumnConstraints();
rightCol.setHgrow(Priority.ALWAYS);
rightCol.setHalignment(HPos.LEFT);
view.getColumnConstraints().addAll(leftCol, rightCol);
GridPane.setHalignment(loginErrorMessage, HPos.CENTER);
GridPane.setHalignment(loginButton, HPos.CENTER);
view.setHgap(10);
view.setVgap(16);
view.setAlignment(Pos.CENTER);
}
public Parent getView() {
return view ;
}
}
public static class MainView {
private BorderPane view ;
public MainView() {
view = new BorderPane();
// *** logout button switches back to a login view: ***
Button logoutButton = new Button("Log out");
logoutButton.setOnAction(event ->
view.getScene().setRoot(new LoginView().getView()));
// Arbitrary UI, irrelevant to this example:
SplitPane splitPane = new SplitPane();
ListView<String> listView = new ListView<>();
IntStream.rangeClosed(1, 10)
.mapToObj(Integer::toString)
.map("Item "::concat)
.forEach(listView.getItems()::add);
Label bigLabel = new Label();
bigLabel.textProperty().bind(
listView.getSelectionModel().selectedItemProperty());
bigLabel.setFont(Font.font("Verdana", FontWeight.BOLD, 18));
BorderPane.setAlignment(bigLabel, Pos.CENTER);
BorderPane.setMargin(bigLabel, new Insets(10));
Label details = new Label();
details.textProperty().bind(
Bindings.when(
listView.getSelectionModel().selectedItemProperty().isNull())
.then("")
.otherwise(Bindings.format("This is where you would display "
+ "all sorts of details about %1$s. "
+ "If %1$s were really a model object, you "
+ "might have a GridPane displaying all its "
+ "properties, for example.",
listView.getSelectionModel().selectedItemProperty())));
details.setWrapText(true);
BorderPane detailsPane = new BorderPane(details, bigLabel, null, null, null);
splitPane.getItems().addAll(listView, detailsPane);
view.setCenter(splitPane);
view.setBottom(logoutButton);
BorderPane.setAlignment(logoutButton, Pos.CENTER);
BorderPane.setMargin(logoutButton, new Insets(8));
BorderPane.setMargin(splitPane, new Insets(16));
}
public Parent getView() {
return view ;
}
}
public static void main(String[] args) {
launch(args);
}
}

Resources