I have an FXML file which has a split pane and 2 rectangles in it. I have both rectangles anchored properly via the FXML but from the code I am generating new rectangles but I can't seem to get the constraints on them working, I set them to the same settings as the rectangles in the FXML(constraint wise) but nothing. I think the issue is the rectangles in the FXML are inside a Split Pane where as the ones generated from the Java code are in the Main AnchorPane. Here is the code any ideas?
public void start(Stage stage) throws Exception {
//GridPane root = new GridPane();
AnchorPane root = fxmlLoader.load(getClass().getClassLoader().getResource("fxml/TestConveyorView.fxml")).getRoot();
Box box = new Box(1);
Rectangle rect = new Rectangle(50,50, box.getStatus().getColor());
rect.setX(385.0);
AnchorPane.setLeftAnchor(rect, 385.0);
AnchorPane.setRightAnchor(rect, 294.0);
root.getChildren().addAll(rect);
Scene scene = new Scene(root);
// BackgroundImage background = new BackgroundImage(null, BackgroundRepeat.REPEAT, BackgroundRepeat.REPEAT, BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT);
stage.setScene(scene);
stage.show();
}
Fixed by removing all the extra code in the main class like below.
public void start(Stage stage) throws Exception {
AnchorPane root = fxmlLoader.load(getClass().getClassLoader().getResource("fxml/TestConveyorView.fxml")).getRoot();
Scene scene = new Scene(root);
// BackgroundImage background = new BackgroundImage(null, BackgroundRepeat.REPEAT, BackgroundRepeat.REPEAT, BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT);
stage.setScene(scene);
stage.show();
}
And adding these to things to my controller
#FXML
AnchorPane Splitright;
Splitright.getChildren().add(rectangle);
As it turns out the shapes were just being thrown on top of everything not actually being placed in the proper AnchorPane, which is what I suspected was happening.
Related
I have a project with maven, javafx and fxml. I have one main BorderPane, welcome.fxml, and Pane, ready.fxml.
My start method is;
#Override
public void start(Stage primaryStage) throws Exception {
try {
Pane root = (Pane) FXMLLoader.load(getClass().getResource("welcome.fxml"));
Scene scene = new Scene(root, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
makeAlert(e, false);
}
}
Now, I have a button in my welcome.fxml, and I want to change my BorderPane's center with ready.fxml. Here is my button handler;
#FXML
private void buttonHandler() throws IOException, InterruptedException {
stage = (Stage) myButton.getScene().getWindow();
Pane sub = (Pane) FXMLLoader.load(getClass().getResource("../ready.fxml"));
BorderPane root = (BorderPane) FXMLLoader.load(getClass().getResource("../welcome.fxml"));
root.setCenter(sub);
//Scene scene = new Scene(root, 640, 480);
//stage.getScene().setRoot(root);
}
UPDATE: Here is my mistake,as #James_D noticed, I load welcome.fxml again in my controller and so, my whole Scene changes insted of only center.
The correct way should be;
stage = (Stage) brokerConnect.getScene().getWindow();
Pane center = (Pane) FXMLLoader.load(getClass().getResource("../ready.fxml"));
// FIXME: Get root like this
BorderPane root = (BorderPane) stage.getScene().getRoot();
root.setCenter(center);
EDITED: Java codes added.
You should update the center of the existing border pane, not create a new one and set the center of the new one.
All you need is to inject the border pane into the controller in the usual way. So add a fx:id to the root element of welcome.fxml:
<!-- imports, etc... -->
<BorderPane fx:id="root" fx:controller="..." xmlns:fx="..." ... >
<!-- ... -->
</BorderPane>
And then in the controller
public class Controller { /* or whatever name you have, again, you can't be bothered to post a MCVE */
#FXML
private BorderPane root ;
#FXML
private void buttonHandler() throws IOException {
Pane sub = (Pane) FXMLLoader.load(getClass().getResource("../ready.fxml"));
root.setCenter(sub);
}
// ...
}
I am a beginner who just recently started learning JavaFX, and I seem to be making the same reoccurring mistake within my programs. For example, in the following code I am trying to draw the X-Axis and Y-Axis and have it binded to half the width and height of the pane. When executed, the axes are very small and located at the topleft corner, but as you resize the window of the application, the axes slowly increase in size until the window not being resized anymore.
public class Debug extends Application {
#Override
public void start(Stage primaryStage) {
Pane pane = new Pane();
GraphFunc test = new GraphFunc();
pane.getChildren().add(test);
Scene scene = new Scene(pane, 500, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
class GraphFunc extends Pane {
private double xAxisSpan, yAxisSpan;
public GraphFunc() {
xAxisSpan = 100;
yAxisSpan = 100;
drawAxes();
}
private void drawAxes() {
Line xAxis = new Line(0, 50, 100, 50);
Line yAxis = new Line(50, 0, 50, 100);
xAxis.setStartX(0);
xAxis.startYProperty().bind(heightProperty().divide(2));
xAxis.endXProperty().bind(widthProperty());
xAxis.endYProperty().bind(heightProperty().divide(2));
yAxis.startXProperty().bind(widthProperty().divide(2));
yAxis.setStartY(0);
yAxis.endXProperty().bind(widthProperty().divide(2));
yAxis.endYProperty().bind(heightProperty());
getChildren().addAll(xAxis, yAxis);
}
}
I am confused because when pane is change to a StackPane, this does not happen. Also if I moved the code in drawAxes() to start() and added the lines to pane it would also not do this. Please explain, I cannot seem to understand what is happening after researching and playing around with it.
This is happening because of Pane. Pane is meant to be used when absolute positioning of children is required.
This is from Oracle documentation:
This class may be used directly in cases where absolute positioning of children is required since it does not perform layout beyond resizing resizable children to their preferred sizes. It is the application's responsibility to position the children since the pane leaves the positions alone during layout.
Pane pane = new Pane();
GraphFunc test = new GraphFunc();
pane.getChildren().add(test);
Scene scene = new Scene(pane, 500, 500);
If you remove the width and height from the scene and instead set the width and height directly on to test like this:
public void start(Stage primaryStage) {
GridPane pane = new GridPane();
GraphFunc test = new GraphFunc();
test.setPrefSize(500, 500);
pane.getChildren().add(test);
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
You will get this:
drawn image
However you will not be able to span.
From Oracle documentation:
Note: if an application needs children to be kept aligned within a
parent (centered, positioned at top-left, etc), it should use a
StackPane instead.
Also from Oracle documentation:
Pane does not clip its content by default, so it is possible that
childrens' bounds may extend outside its own bounds, either if
children are positioned at negative coordinates or the pane is resized
smaller than its preferred size.
Here is my summary code
public class KlArgon extends Application {
BorderPane border ;
Scene scene ;
Stage stage;
#Override
public void start(Stage stage) {
:
border = new BorderPane();
:
HBox infoBox = addInfoHBox();
border.setTop(infoBox);
:
VBox menuBox = addMenuVBox();
border.setLeft(menuBox);
:
border.setCenter(addAnchorPane(addGridPane()));
// setRight and setBottom is not used
:
scene = new Scene (border);
stage.setScene(scene);
stage.show();
}
private Node addAnchorPane(GridPane grid) {
AnchorPane anchorpane = new AnchorPane();
anchorpane.getChildren().add(grid);
AnchorPane.setTopAnchor(grid, 10.0);
return anchorpane;
}
private GridPane addGridPane() {
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(0, 10, 0, 10));
grid.add(addWhiteboard(), 1, 0);
return grid;
}
private Node addWhiteboard() {
Canvas canvas = new Canvas (wboardWd, wdboardHt);
GraphicsContext gc = canvas.getGraphicsContext2D();
drawShapes(gc);
drawfromClipboard(gc);
return canvas;
}
}
I refer to the Center pane as the "Whiteboard". Among other things, I have two buttons in menuBox - btnCopyFromClipboard and btnClearWhiteboard.
When user presses btnCopyFromClipboard - the user should be able to draw an rectangle in the "Whiteboard" only (i.e. Center pane only) and then the clipboard image will be copied (scaled) into that rectangle.
So I made border,scene, stage as global and I am trying to get this to work - not only it is buggy/ugly- to me it looks like a hack. Is there a cleaner way to do this i.e. manage Center Pane when button in left pane is pressed?
Basically I want the Center Pane to be the Canvas and the GraphicsContext operations are performed whe the Buttons in Left Pane is pressed.
What I have working is pressing the btnCopyFromClipboard lets me draw the rectangle anywhere/everywhere (instead of limiting it to the Center Pane / the whiteboard). I want to restrict the rectangle to be drawn inside the Center Pane / the whiteboard only.
Some inputs/pointers from someone who has been through this will be very much appreciated.
http://docs.oracle.com/javafx/2/layout/builtin_layouts.htm was helpful to get me started.
I was in a fix as well and here is a question which I asked in Oracle Forums, to which, James gave me a vivid reply. Please go through this, it has your answer
https://community.oracle.com/thread/2598756
I want to resize an Rectangle shape from JavaFX accordingly with a TextField which automatically resize on Window resize using Anchors.
I tried add anchors to the rectangle also but it won't resize from the width I set from SceneBuilder.
So short story: when my TextField resizes because my Window resize the Rectangle should resize to the same width as the TextField. Thanks
You can bind the rectangle's width to the text field's:
myRectangle.widthProperty().bind(myTextField.widthProperty());
Example:
public class Demo extends Application {
#Override
public void start(Stage stage) {
Group root = new Group();
Scene scene = new Scene(root);
stage.setScene(scene);
TextField myTextField = new TextField("default");
Rectangle myRectangle = new Rectangle();
myRectangle.setHeight(30);
myRectangle.setFill(Color.AQUA);
myRectangle.widthProperty().bind(myTextField.widthProperty());
final VBox hb = new VBox(10);
hb.setPadding(new Insets(5));
hb.getChildren().addAll(myTextField, myRectangle);
scene.setRoot(hb);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I am using JavaFX 2 in Netbeans. How do I get the width and height of an element to adjust when the Frame is resized? Here is my layout:
Stage stage = new Stage();
stage.setTitle("Hello World");
final Group root = new Group();
Scene scene = new Scene(root);
BorderPane border = new BorderPane();
border.setPrefWidth(stage.getWidth());
border.setPrefHeight(stage.getHeight());
HBox outerHBox = new HBox();
border.setCenter(outerHBox);
root.getChildren().add(border);
stage.setScene(scene);
After some more research
I found where this has been done before http://java.dzone.com/articles/setting-stage-javafx-sdk but it is in an older FX (very different from JavaFX 2). I am having trouble translating it. Looks like I should be using binding? I've never used binding before and I've barely used FX.
Whats the best way to accomplish this?
Not all Node classes enable resizing. The Group class is one of these. You'll understand this when calling isResizable() on your root object. Use instead a subclass of Region e.g. BorderPane as your root.
Stage stage = new Stage();
stage.setTitle("Hello World");
final BorderPane border = new BorderPane();
Scene scene = new Scene(border);
Button button = new Button("test");
HBox outerHBox = new HBox();
outerHBox.getChildren().add(button);
outerHBox.setAlignment(Pos.CENTER);
border.setCenter(outerHBox);
stage.setScene(scene);
Your example should work, now.