The code below should move the Label based on the position of the horizontal scroll bar so that the Label appears to remain stationary. This almost works perfectly however when you move the scrollbar to the end the label has moved slightly so it does not look like it is in the same position.
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class LblMoves extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
try {
VBox images = new VBox();
images.setPadding(new Insets(0, 0, 0, 0));
Label posLbl = new Label("0");
images.getChildren().add(posLbl);
images.setPrefSize(Integer.MAX_VALUE, 50);
ScrollPane scrollPane = new ScrollPane(images);
scrollPane.setStyle("-fx-background: #FFFFFF;");
scrollPane.hvalueProperty().addListener(new ChangeListener<Number>() {
public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) {
double screenPer = scrollPane.getHvalue() * scrollPane.getWidth();
double pos = scrollPane.getHvalue() * images.getWidth();
double marg = pos - screenPer;
posLbl.setPadding(new Insets(0, 0, 0, marg));
}
});
Scene scene = new Scene(scrollPane, 600, 600);
primaryStage.setScene(scene);
primaryStage.setMaximized(true);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
}
You use the width of the ScrollPane. However the width used in the calculations for ScrollPane use the viewportBounds.
Also since by default the position is rounded to full pixels, which causes some movement of the Label (which could be fixed by using translateX instead of the padding).
InvalidationListener listener = o -> {
double marg = (images.getWidth() - scrollPane.getViewportBounds().getWidth()) * scrollPane.getHvalue();
posLbl.setTranslateX(marg);
// posLbl.setPadding(new Insets(0, 0, 0, marg));
};
scrollPane.hvalueProperty().addListener(listener);
scrollPane.viewportBoundsProperty().addListener(listener);
listener.invalidated(null);
Related
I'm new to JavaFX, trying to build a GUI program that displays a bill for a table at a restaurant when you click on that table. The spacing is off between the table buttons and I'm not sure why.
The GUI class for my program:
package restaurantBillingProgram;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.geometry.Pos;
public class BillingGUI extends Application {
#Override
public void start(Stage primaryStage) {
// Create grid pane
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
pane.setHgap(5);
pane.setVgap(5);
// Label
pane.add(new Label("Generate bill"), 1, 0);
// Buttons
Button btT1 = new Button("Table 1");
pane.add(btT1, 0, 1);
btT1.setOnAction(e - > Billing.generateT1());
Button btT2 = new Button("Table 2");
pane.add(btT2, 1, 1);
btT2.setOnAction(e - > Billing.generateT2());
Button btT3 = new Button("Table 3");
pane.add(btT3, 2, 1);
btT3.setOnAction(e - > Billing.generateT3());
// Create scene and place in stage
Scene scene = new Scene(pane, 250, 250);
primaryStage.setTitle("Restaurant Billing Program");
primaryStage.setScene(scene);
primaryStage.show();
}
// Main method
public static void main(String[] args) {
launch(args);
}
}
From the Javadoc:
Row/Column Sizing
By default, rows and columns will be sized to fit their content; a column will be wide enough to accommodate the widest child, ...
The label in row 0 column 1 forces that column to be wider.
You probably want the label to be centered and span all 3 columns.
While doing you layout, use pane.setGridLinesVisible(true). This should only be used during debugging. It can be very useful for situations like your current situation. As #Jim Garrison pointed out, your Label is causing the issue:
Issue:
One way to fix this is to let the Label span all columns and center the Label's text.
Fix:
Key Code:
label.setMaxWidth(Double.MAX_VALUE);
label.setAlignment(Pos.CENTER);
pane.add(label, 0, 0, 3, 1);// Look at the following link to see how this add method works. https://openjfx.io/javadoc/11/javafx.graphics/javafx/scene/layout/GridPane.html#add(javafx.scene.Node,int,int,int,int)
Full Code:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.geometry.Pos;
public class BillingGUI extends Application {
#Override
public void start(Stage primaryStage) {
// Create grid pane
GridPane pane = new GridPane();
pane.setAlignment(Pos.CENTER);
pane.setHgap(5);
pane.setVgap(5);
pane.setGridLinesVisible(true);//Use for debugging only!!!!
// Label
Label label = new Label("Generate bill");
label.setMaxWidth(Double.MAX_VALUE);
label.setAlignment(Pos.CENTER);
pane.add(label, 0, 0, 3, 1);
// Buttons
Button btT1 = new Button("Table 1");
pane.add(btT1, 0, 1);
Button btT2 = new Button("Table 2");
pane.add(btT2, 1, 1);
Button btT3 = new Button("Table 3");
pane.add(btT3, 2, 1);
// Create scene and place in stage
Scene scene = new Scene(pane, 250, 250);
primaryStage.setTitle("Restaurant Billing Program");
primaryStage.setScene(scene);
primaryStage.show();
}
// Main method
public static void main(String[] args) {
launch(args);
}
}
I have a number of nodes in a group, whose visibility I would like to control using the visibleProperty(). I have observed that turning visibility of an element off affects the layout bounds of the group. They are recalculated as if the element wasn't there at all, not just wasn't visible. Is there a way to keep the presence of a node, but just turn off its visibility, so that the layout bounds were adjusted as if the node was there the whole time?
Example to ilustrate the problem, let's assume that the nodes are circles below.
Circle c1 = new Circle(0.0, 0.0, 3); // radius is 3
Circle c2 = new Circle(10.0, 10.0, 3);
Circle c3 = new Circle(20.0, 20.0, 3);
Group g = new Group();
g.getChildren().addAll(c1, c2, c3);
Bounds b1 = g.getLayoutBounds();
c3.visibleProperty().setValue(false);
Bounds b2 = g.getLayoutBounds();
Above bounds b and b2 will span:
b1 = BoundingBox [minX:-3.0, minY:-3.0, minZ:0.0, width:26.0, height:26.0, depth:0.0, maxX:23.0, maxY:23.0, maxZ:0.0]
b2 = BoundingBox [minX:-3.0, minY:-3.0, minZ:0.0, width:16.0, height:16.0, depth:0.0, maxX:13.0, maxY:13.0, maxZ:0.0]
Bounds b2 are calculated after turning off the visibility of circle c3, so they shrinked with respect to the original bounds b1. I would like to have the method of having the bounds expanded to b1, even though some elements in the group are not visible.
Edit
Minimal reproducible example:
package sample;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Bounds;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.layout.HBox;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Circle c1 = new Circle(0.0, 0.0, 3); // radius is 3
Circle c2 = new Circle(10.0, 10.0, 3);
Circle c3 = new Circle(20.0, 20.0, 3); // radius is 3
Circle c4 = new Circle(30.0, 30.0, 3);
Group g1 = new Group();
Group g2 = new Group();
g1.getChildren().addAll(c1, c2);
g2.getChildren().addAll(c3, c4);
Group main = new Group(g1, g2);
CheckBox checkBox1 = new CheckBox("Show");
g2.visibleProperty().bind(checkBox1.selectedProperty());
Bounds b1 = main.getLayoutBounds();
System.out.println(b1);
checkBox1.selectedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean aBoolean, Boolean t1) {
System.out.println(main.getLayoutBounds());
}
});
HBox hbox = new HBox(checkBox1, main);
Scene scene = new Scene(hbox, 400, 300);
primaryStage.setTitle("Hello Stackoverflow, are you happy now?");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Now, any time you select the checkbox, not only 2 of 4 circles appear, but you will also see that layout bounds of the group change. The problem is that I need to know all the time the layout bounds as if all the groups were visible. I can't store the bounds value when they are all visible, because for simplicity I included here only 4 circles, while in real application, they are in thousands and they are moving around also when not visible, and there are also other objects of different sizes bound to them, which may expand the layout bounds of the main group even more.
Updated solution.
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Shape;
public class ShapesGroup extends Group {
public final BooleanProperty transparentProperty = new SimpleBooleanProperty();
private final ObservableList<Shape> shapes = FXCollections.observableArrayList();
public ShapesGroup() {
Bindings.bindContent(getChildren(), shapes);
shapes.addListener((ListChangeListener<Shape>) change -> {
while (change.next()) {
if (change.wasAdded()) {
for (Shape shape : change.getAddedSubList()) {
shape.fillProperty().addListener((ChangeListener<Paint>) (observable, oldFill, newFill) -> {
transparentProperty.addListener((ChangeListener<Boolean>) (observable1, oldTransparent, newTransparent) -> {
if (!newTransparent) {
shape.setFill(oldFill);
}
});
});
transparentProperty.addListener((ChangeListener<Boolean>) (observable, oldValue, newValue) -> {
if (newValue) {
shape.setFill(Color.TRANSPARENT);
}
});
}
}
}
});
}
public ObservableList<Shape> getShapes() {
return shapes;
}
}
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class MainApp extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Rectangle rectangle = new Rectangle(40, 40, Color.YELLOW);
Circle circle = new Circle(20, Color.RED);
ShapesGroup group = new ShapesGroup();
group.getShapes().addAll(rectangle, circle);
StackPane stackPane = new StackPane(group);
Button button = new Button("Switch");
VBox vBox = new VBox(stackPane, button);
VBox.setVgrow(stackPane, Priority.ALWAYS);
Scene scene = new Scene(vBox, 400, 400);
stage.setScene(scene);
stage.show();
button.setOnAction(event -> {
group.transparentProperty.set(!group.transparentProperty.get());
});
}
}
I'm just working on a little project and started to get in JavaFX.
I have a problem and I don't know any solutions..
So I managed it to bring a Scrollbar(incl Listener) into the root.
But the listener doesn't work.
I want to add many comboboxes one below the other and when I reached the scenesize(LayoutX) it should be possible to scrolldown.
How can I solve my problem?
package application;
import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.Pane;
import javafx.scene.text.*;
import javafx.stage.Stage;
import application.XMLActions;;
public class Main extends Application {
/**
* Globale Variablen
*/
int abstandszaehler = 0;
private Pane root = new Pane();
private ScrollBar sB = new ScrollBar();
private XMLActions xA = new XMLActions();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("XML-Zeilenersteller");
primaryStage.setResizable(false);
/**
* Elemente für die Root
*/
//Buttons
Button newXMLLine = new Button();
newXMLLine.setText("Einfügen neuer XML-Zeile");
newXMLLine.setLayoutX(735);
newXMLLine.setLayoutY(80);
newXMLLine.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
setComboBox();
}
});
Button newXMLDocument = new Button();
newXMLDocument.setText("Erstelle XML-Dokument");
newXMLDocument.setLayoutX(735);
newXMLDocument.setLayoutY(550);
newXMLDocument.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
System.out.println("Test2");
}
});
//Überschrift
Text header = new Text(105, 50, "XML Lines Creator");
header.setFont(new Font(30)); header.setStyle("-fx-underline: true;");
//Scrollbar
sB.setLayoutX(715);
sB.setLayoutY(80);
sB.setMin(0);
sB.setOrientation(Orientation.VERTICAL);
sB.setPrefHeight(500);
sB.setMax(360);
sB.setUnitIncrement(30);
sB.setBlockIncrement(35);
sB.valueProperty().addListener((ObservableValue<? extends Number> ov,
Number old_val, Number new_val) -> {
System.out.println(-new_val.doubleValue());
});
/**
* Hauptseite als Root
* Rootbearbeitungen
*/
root.setStyle("-fx-background-color: lightsteelblue");
root.getChildren().addAll(sB,newXMLDocument,header,newXMLLine );
//Scene setzen
Scene mainScene = new Scene(root, 900, 600);
primaryStage.setScene(mainScene);
primaryStage.show();
}
public void setComboBox(){
ComboBox cB = new ComboBox(xA.getList());
root.getChildren().add(cB);
cB.setLayoutX(80);
cB.setLayoutY(80 + abstandszaehler);
abstandszaehler = abstandszaehler + 30;
}
}
EDIT 1:
I got a little progress with that code in the listener:
root.setLayoutY(-new_val.doubleValue());
Replace the Pane with a ScrollPane. On the ScrollPane you can define the policy for your scrollbar.
If you define it like this, it will behave like a Pane:
ScrollPane sp = new ScrollPane();
sp.setHbarPolicy(ScrollBarPolicy.NEVER);
sp.setVbarPolicy(ScrollBarPolicy.NEVER);
Take a look at this article by Oracle.
First, if you wish to layout controls vertically consider using VBox. This VBox should then be enclosed by a ScrollPane.
If you then set the VBox's prefHeight to Control.USE_COMPUTED_SIZE and maxHeight to Double.POSITIVE_INFINITY the VBox should resize to fit it's content without limit, and the enclosing ScrollPane should show and hide scrollbars as necessary.
I am new to JavaFX and I am trying to display a rational number.
For example for the number 5/7 I want the program to show the following:
Here is the code I've tried to use in order to get the result (but it shows nothing but a blank white pane):
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.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
public class Main extends Application {
Font fontLarge = Font.font("Droid Sans", FontWeight.BOLD, 15);
Font fontSmall = Font.font("Droid Sans", FontWeight.BOLD, 10);
#Override
public void start(Stage stage) {
Group root = new Group();
Scene scene = new Scene(root, 200, 200);
root.getChildren().add(getBoxOfRationalNumber("5", "7"));
scene.setRoot(root);
stage.setScene(scene);
stage.show();
}
public VBox getBoxOfRationalNumber(String theNum, String theDenom) {
VBox vb = new VBox();
final Canvas num = new Canvas();
final Canvas denom = new Canvas();
final Canvas line = new Canvas();
GraphicsContext gNum = num.getGraphicsContext2D();
GraphicsContext gDenom = denom.getGraphicsContext2D();
GraphicsContext gLine = line.getGraphicsContext2D();
gLine.setFont(fontLarge);
gNum.setFont(fontLarge);
gDenom.setFont(fontLarge);
gLine.fillText("______", 0, 0);
gNum.fillText(theNum, 0, 0);
gDenom.fillText(theDenom, 0, 0);
vb.getChildren().add(num);
vb.getChildren().add(line);
vb.getChildren().add(denom);
return vb;
}
public static void main(String[] args) {
launch(args);
}
}
Although, you could use a canvas for this, I advise to not try to solve this problem with a canvas. In your case, using only scene graph nodes rather than canvas is most likely a more appropriate solution to your problem.
Here is a sample solution using scene graph nodes.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Line;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class FractionDisplay extends Application {
private class Fraction extends VBox {
private double offset;
public Fraction(int numerator, int denominator) {
init(numerator + "", denominator + "");
}
public Fraction(String numerator, String denominator) {
init(numerator, denominator);
}
private void init(String numerator, String denominator) {
setAlignment(Pos.CENTER);
Text numeratorText = new Text(numerator);
Text denominatorText = new Text(denominator);
offset = numeratorText.getBaselineOffset() * 1.5;
double dividerWidth =
Math.max(
numeratorText.getLayoutBounds().getWidth(),
denominatorText.getLayoutBounds().getWidth()
) + 6;
Line divider = new Line(0, 1, dividerWidth, 1);
divider.setStrokeWidth(2);
getChildren().addAll(
numeratorText,
divider,
denominatorText
);
}
public double getBaselineOffset() {
return offset;
}
}
#Override
public void start(Stage stage) {
TextFlow flow = new TextFlow(
new Text("In mathematics, the infinite series "),
new Fraction(1, 2),
new Text(" - "),
new Fraction(1, 4),
new Text(" + "),
new Fraction(1, 8),
new Text(" - "),
new Fraction(1, 16),
new Text(" . . . "),
new Text(" is a simple example of an alternating series that converges absolutely.")
);
flow.setPadding(new Insets(5));
Scene scene = new Scene(flow, 300, 100);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Of course, the above is a pretty simplistic and incomplete solution to a general issue of typesetting math. If you need sophisticated mathematics typesetting, you could use something like MathJax in a WebView.
The main problem of your code seems to be that the canvases don't have a size. But the whole code seems to be a strange mixture of concepts for me.
Why do you use three separate canvases? Why do you combine them with a VBox? Would you do all that too if you were just writing on a piece of paper?
I want to create a refresh button for my webView that will be on top of the view (even if it hides part of the view), when I place the button on the Grid Pane it pushes the webView down or to the side (depends where I place the button)
How can I place my "refresh" button on top of the webView and not move it aside?
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class webviewbrowser extends Application {
#Override public void start(Stage primaryStage) throws Exception {
Pane root = new WebViewPane();
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.setFullScreen(true);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
/**
* Create a resizable WebView pane
*/
public class WebViewPane extends Pane {
public WebViewPane() {
VBox.setVgrow(this, Priority.ALWAYS);
setMaxWidth(Double.MAX_VALUE);
setMaxHeight(Double.MAX_VALUE);
WebView view = new WebView();
view.setMinSize(500, 400);
view.setPrefSize(500, 400);
final WebEngine eng = view.getEngine();
eng.load("http://google.com");
//final TextField locationField = new TextField("http://www.google.com");
//locationField.setMaxHeight(Double.MAX_VALUE);
Button goButton = new Button("Refresh");
goButton.setDefaultButton(true);
EventHandler<ActionEvent> goAction = new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
eng.reload();
}
};
goButton.setOnAction(goAction);
GridPane grid = new GridPane();
grid.setVgap(0);
grid.setHgap(0);
GridPane.setConstraints(goButton,2,0,2,1, HPos.RIGHT, VPos.BOTTOM, Priority.ALWAYS, Priority.ALWAYS);
GridPane.setConstraints(view, 0, 0, 2, 1, HPos.CENTER, VPos.CENTER, Priority.SOMETIMES, Priority.SOMETIMES);
grid.getColumnConstraints().addAll(
new ColumnConstraints(100, 100, Double.MAX_VALUE, Priority.ALWAYS, HPos.CENTER, true),
new ColumnConstraints(40, 40, 40, Priority.NEVER, HPos.CENTER, true)
);
grid.getChildren().addAll(goButton, view);
getChildren().add(grid);
}
#Override protected void layoutChildren() {
List<Node> managed = getManagedChildren();
double width = getWidth();
double height = getHeight();
double top = getInsets().getTop();
double right = getInsets().getRight();
double left = getInsets().getLeft();
double bottom = getInsets().getBottom();
for (int i = 0; i < managed.size(); i++) {
Node child = managed.get(i);
layoutInArea(child, left, top,
width - left - right, height - top - bottom,
0, Insets.EMPTY, true, true, HPos.CENTER, VPos.CENTER);
}
}
}
}
If you want to stack one component on top of another, don't use a GridPane for layout, instead use a parent that allows layout components to be placed on top of one another. For example, a standard Pane, a StackPane, Group or Region. In these stacked style layouts, the components are rendered in order of the child component's position in the parent's child list.
In your sample code you are already extending Pane, so get rid of all of the grid code and just do:
getChildren().addAll(view, goButton);
instead of:
grid.getChildren().addAll(goButton, view);
Modify the layout properties of your goButton to position it within a parent which does not manage the layout position of it's children, e.g. you can call goButton.relocate(xPos, yPos).
You have some custom stuff in the layoutChildren method you override that may mess up the default Pane layout processing logic. Overriding layoutChildren is more of an advanced layout topic and I wouldn't advise it for beginners.
Here is an updated sample you could look at which uses some of the concepts mentioned in this answer.
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.web.*;
import javafx.stage.Stage;
public class WebViewBrowser extends Application {
#Override public void start(Stage stage) throws Exception {
stage.setScene(new Scene(new WebViewPane("http://google.com")));
stage.setFullScreen(true);
stage.show();
}
public static void main(String[] args) { launch(args); }
}
class WebViewPane extends Pane {
final WebView view = new WebView();
final Button goButton = createGoButton(view.getEngine());
public WebViewPane(String initURL) {
view.getEngine().load(initURL);
getChildren().addAll(
view,
goButton
);
initLayout();
}
private Button createGoButton(final WebEngine eng) {
Button go = new Button("Refresh");
go.setDefaultButton(true);
go.setOnAction(new EventHandler<ActionEvent>() {
#Override public void handle(ActionEvent event) {
eng.reload();
}
});
return go;
}
private void initLayout() {
setMinSize(500, 400);
setPrefSize(1024, 768);
view.prefWidthProperty().bind(widthProperty());
view.prefHeightProperty().bind(heightProperty());
goButton.setLayoutX(10);
goButton.layoutYProperty().bind(
heightProperty().subtract(20).subtract(goButton.heightProperty())
);
}
}