Building BorderPane with SplitPanes and minimize areas to hide nodes - javafx

I am trying to build an BorderPane with SplitPanes to get a BorderPane which has resizeable areas by dragging the mouse. I have write some code which is working. But i cant hide the areas of the SplitPanes if there any nodes inside.
First of all i have build this stage and it works.
public class Example extends Application {
StackPane gui;
SplitPane splitVertical;
SplitPane splitHorizontal;
StackPane top;
StackPane left;
StackPane center;
StackPane right;
StackPane bottom;
#Override
public void start(Stage stage) throws Exception {
splitVertical = new SplitPane();
splitVertical.setOrientation(Orientation.VERTICAL);
splitVertical.setDividerPosition(0, 0.25);
splitVertical.setDividerPosition(1, 0.75);
splitVertical.setDividerPosition(2, 1.00);
splitHorizontal = new SplitPane();
splitHorizontal.setOrientation(Orientation.HORIZONTAL);
splitHorizontal.setDividerPosition(0, 0.25);
splitHorizontal.setDividerPosition(1, 0.75);
splitHorizontal.setDividerPosition(2, 1.00);
top = new StackPane();
left = new StackPane();
center = new StackPane();
right = new StackPane();
bottom = new StackPane();
splitVertical.getItems().add(top);
splitVertical.getItems().add(splitHorizontal);
splitHorizontal.getItems().add(left);
splitHorizontal.getItems().add(center);
splitHorizontal.getItems().add(right);
splitVertical.getItems().add(bottom);
gui = new StackPane(splitVertical);
Scene scene = new Scene(gui, 400, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
This code works fine. I have a "BorderPane" with all areas.
And i can resize the areas like i want and hide them completely, if i want.
But if there any nodes inside the areas, i cant hide the areas. I just can minimize them until the node is accepts. Here is an example.
public class Example extends Application {
StackPane gui;
SplitPane splitVertical;
SplitPane splitHorizontal;
StackPane top;
StackPane left;
StackPane center;
StackPane right;
StackPane bottom;
Button buttonTop;
Button buttonLeft;
Button buttonCenter;
Button buttonRight;
Button buttonBottom;
#Override
public void start(Stage stage) throws Exception {
splitVertical = new SplitPane();
splitVertical.setOrientation(Orientation.VERTICAL);
splitVertical.setDividerPosition(0, 0.25);
splitVertical.setDividerPosition(1, 0.75);
splitVertical.setDividerPosition(2, 1.00);
splitHorizontal = new SplitPane();
splitHorizontal.setOrientation(Orientation.HORIZONTAL);
splitHorizontal.setDividerPosition(0, 0.25);
splitHorizontal.setDividerPosition(1, 0.75);
splitHorizontal.setDividerPosition(2, 1.00);
buttonTop = new Button("Top");
buttonLeft = new Button("Left");
buttonCenter = new Button("Center");
buttonRight = new Button("Right");
buttonBottom = new Button("Bottom");
top = new StackPane(buttonTop);
left = new StackPane(buttonLeft);
center = new StackPane(buttonCenter);
right = new StackPane(buttonRight);
bottom = new StackPane(buttonBottom);
splitVertical.getItems().add(top);
splitVertical.getItems().add(splitHorizontal);
splitHorizontal.getItems().add(left);
splitHorizontal.getItems().add(center);
splitHorizontal.getItems().add(right);
splitVertical.getItems().add(bottom);
gui = new StackPane(splitVertical);
Scene scene = new Scene(gui, 400, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
I got a BorderPane.
But i cant hide the areas completely.
Is it possible to change the size of the areas until they are completely hide?

I have found the solution. The minSize of the childnode has set to 0. Then everything works fine.
buttonTop.setMinSize(0, 0);
buttonLeft.setMinSize(0, 0);
buttonCenter.setMinSize(0, 0);
buttonRight.setMinSize(0, 0);
buttonBottom.setMinSize(0, 0);

Related

How to make a GridPane right of BorderPane closeable?

I have code in the form:
<BorderPane>
...
<right>
<GridPane>
...
</GridPane>
</right>
...
</BorderPane>
Obviously, now the GridPane takes a big space right of my BorderPane. What I'd like to do is add a button (or another element) that minimizes and maximizes the GridPane, so it's only fully in the view of the user when it is really needed. How can I easily achieve this?
You can do what you want by setting the Visible and Managed properties of your GridPane off and on. The centre of the BorderPane will automatically expand to take over the entire width of the BorderPane. "Managed" controls whether or not the layout manager will leave space for the node, so if you just turn Visible off, then you'll have an unused area the size of your GridPane on the right. The following code demonstrates it, I put the buttons in a VBox with a border around it so that you can see how it expands:
public class ResizeRight extends BorderPane {
public ResizeRight() {
Button openButton = new Button("Open");
Button closeButton = new Button("Close");
GridPane gridPane = new GridPane();
gridPane.addRow(0, new Text("This is just some text"));
gridPane.addRow(1, new Text("This is just some more text"));
VBox vbox = new VBox(10, openButton, closeButton);
vbox.setBorder(new Border(new BorderStroke(Color.BLACK,
BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
setCenter(vbox);
setRight(gridPane);
setPadding(new Insets(10));
openButton.setOnAction(evt -> {
gridPane.setVisible(true);
gridPane.setManaged(true);
});
closeButton.setOnAction(evt -> {
gridPane.setVisible(false);
gridPane.setManaged(false);
});
}
}
Run it from something like this:
public class Sample1 extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
Scene scene = new Scene(new ResizeRight(), 300, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
}

Javafx BorderPane with 2 GridPanes, second GridPane not showing up

I need two grids in a BorderPane which is placed in a tab. When I add them both everything seems fine, but on launch only the first grid is visible.
This is my code.
public void start(Stage stage) throws Exception {
BorderPane bp = new BorderPane();
GridPane g1 = new GridPane();
g1.add(new Button("b1"), 0, 0);
GridPane g2 = new GridPane();
g2.add(new Button("b2"), 0, 0);
bp.setCenter(g1);
bp.setBottom(g2);
TabPane p = new TabPane();
Tab tab = new Tab("Test tab");
tab.setContent(bp);
p.getTabs().add(tab);
Scene s = new Scene(p);
stage.setScene(s);
stage.show();
}
g2 is not showing up at all. What am I missing?

Border Pane issues

I want to make a border pane with two HBoxes on top and bottom and a GridPane in the center... I wrote what I needed, attached the labels but I can't run the code
Exception in Application start method
java.lang.reflect.InvocationTargetException is what I get as an error... the code is below, any help is welcome :) thanks
public class labelBorder extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane bp = new BorderPane();
bp.setPrefSize(400, 400);
HBox hb1 = new HBox();
Label lb1 = new Label("");
lb1.setPrefWidth(200);
lb1.setBorder(new Border(new BorderStroke(Color.AQUAMARINE,BorderStrokeStyle.SOLID,null,new BorderWidths(5))));
Label lb2 = new Label("");
lb2.setPrefWidth(200);
lb2.setBorder(new Border(new BorderStroke(Color.BLUEVIOLET,BorderStrokeStyle.SOLID,null,new BorderWidths(5))));
HBox hb2 = new HBox();
URI foto = Paths.get("D:\\Barca.jpg").toUri();
Label lb3 = new Label();
lb3.setGraphic(new ImageView(foto.toString()));
lb3.autosize();
GridPane gp = new GridPane();
Label lb4 = new Label("");
Label lb5 = new Label("");
Label lb6 = new Label("");
Label lb7 = new Label("");
gp.add(lb4, 0, 0);
gp.add(lb5, 0, 1);
gp.add(lb6, 1, 0);
gp.add(lb7, 1, 1);
gp.getChildren().addAll(lb4,lb5,lb6,lb7);
hb1.getChildren().addAll(lb1,lb2);
hb2.getChildren().addAll(lb3);
bp.setTop(hb1);
bp.setCenter(gp);
bp.setBottom(hb2);
bp.getChildren().addAll(hb1,hb2,gp);
Scene scene = new Scene(bp);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You should NOT add the duplicate children controls to your parent layout(pane). Your code must be throwing,
java.lang.IllegalArgumentException: Children: duplicate children added
To overcome your issue remove these lines,
gp.getChildren().addAll(lb4,lb5,lb6,lb7);
And,
bp.getChildren().addAll(hb1,hb2,gp);
As those controls have already been added to your corresponding layout.
Note: Adding children with pane.getChildren().addAll(...) on BorderPane is irrelevant and will be ignored while rendering the added controls.

javafx - Navigation Sidebar with Toggle

So in windows 10 you have the windows menu with the icons on the left side:
When clicking on the hamburger icon the menu expands and text is show.
The expanded part is overlaying the content. The text is showing. and it was animated in (sliding transition).
In my application I want to make a similar menu on the right side (see blue part):
I have absolutely no idea how to get this effect. Currently I made a button with a graphic. I only display the graphic and when I click on the hamburger I show all the text by changing the setContentDisplay(ContentDisplay.GRAPHIC_ONLY) to setContentDisplay(ContentDisplay.RIGHT) 2 things that are wrong with this approach.
it pushes the content.
You cannot add a transition.
Any help would be appreciated, especially examples.
Demo
I made a demo that shows what I currently have:
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
JFXButton[] jfxButtons = {
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
};
JFXHamburger hamburger = new JFXHamburger();
HamburgerNextArrowBasicTransition transition = new HamburgerNextArrowBasicTransition(hamburger);
transition.setRate(-1);
hamburger.setAlignment(Pos.CENTER_RIGHT);
hamburger.setPadding(new Insets(5));
hamburger.setStyle("-fx-background-color: #fff;");
hamburger.setOnMouseClicked(event -> {
transition.setRate(transition.getRate() * -1);
transition.play();
if (transition.getRate() == -1) {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
} else {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.RIGHT);
}
}
});
ScrollPane scrollPane = new ScrollPane();
VBox vBox = new VBox();
scrollPane.setContent(vBox);
vBox.getStyleClass().add("content_scene_right");
vBox.getChildren().add(hamburger);
vBox.getChildren().addAll(jfxButtons);
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setMaxWidth(Double.MAX_VALUE);
jfxButton.setRipplerFill(Color.valueOf("#40E0D0"));
VBox.setVgrow(jfxButton, Priority.ALWAYS);
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
vBox.setFillWidth(true);
Label labelHoverOverTest = new Label("Testing label");
VBox vbox2 = new VBox();
vbox2.getChildren().addAll(labelHoverOverTest);
vbox2.setAlignment(Pos.CENTER_RIGHT);
root.setRight(scrollPane);
root.setCenter(vbox2);
Scene scene = new Scene(root);
primaryStage.setMinWidth(400);
primaryStage.setMinHeight(400);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I used JFoenix and fontawesomefx for this demo, but it can also be javafx scene buttons with any graphic.
Here are some images of what the demo looks like:
As you can see it pushes it the content in the center and I can't add any transition.
(here is a sample from bootstrap to give you an idea on What I'm trying to make it look like 1: https://bootsnipp.com/snippets/Pa9xl, 2: https://bootsnipp.com/snippets/featured/navigation-sidebar-with-toggle (with this one the content still moves, but it should give you a clear idea on what my vision is))
Problem is that you are using BorderPane and placing everything on same layer, so when content on right changes width it will affect one in the center and such.
In other to avoid this you should make it layered, so for root of view use StackPane, this pane should have 2 children, 1 for main content and 1 for sidebar, make sure that sidebar is above main content, now this 2 can be any Pane that you want. This way sidebar will be placed over main content and it won't push content.
Using code you provided and just adding StackPane you get something like this:
#Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
BorderPane mainContent = new BorderPane();
BorderPane sidebar = new BorderPane();
JFXButton[] jfxButtons = {
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),
new JFXButton("Some text", new FontAwesomeIconView(FontAwesomeIcon.LINK)),};
JFXHamburger hamburger = new JFXHamburger();
HamburgerNextArrowBasicTransition transition = new HamburgerNextArrowBasicTransition(hamburger);
transition.setRate(-1);
hamburger.setAlignment(Pos.CENTER_RIGHT);
hamburger.setPadding(new Insets(5));
hamburger.setStyle("-fx-background-color: #fff;");
hamburger.setOnMouseClicked(event -> {
transition.setRate(transition.getRate() * -1);
transition.play();
if (transition.getRate() == -1) {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
} else {
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setContentDisplay(ContentDisplay.RIGHT);
}
}
});
ScrollPane scrollPane = new ScrollPane();
VBox vBox = new VBox();
scrollPane.setContent(vBox);
vBox.getStyleClass().add("content_scene_right");
vBox.getChildren().add(hamburger);
vBox.getChildren().addAll(jfxButtons);
for (JFXButton jfxButton : jfxButtons) {
jfxButton.setMaxWidth(Double.MAX_VALUE);
jfxButton.setRipplerFill(Color.valueOf("#40E0D0"));
VBox.setVgrow(jfxButton, Priority.ALWAYS);
jfxButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
vBox.setFillWidth(true);
Label labelHoverOverTest = new Label("Testing label");
VBox vbox2 = new VBox();
vbox2.getChildren().addAll(labelHoverOverTest);
vbox2.setAlignment(Pos.CENTER_RIGHT);
mainContent.setCenter(vbox2);
sidebar.setRight(scrollPane);
root.getChildren().addAll(mainContent, sidebar);
Scene scene = new Scene(root);
primaryStage.setMinWidth(400);
primaryStage.setMinHeight(400);
primaryStage.setScene(scene);
primaryStage.show();
}
As for transition I'm not sure what is problem there, for me it works fine.

JavaFX. How to make the border of imageview, when I click the imageview?

In javaFX, I want make a imageview that can change border when I click.
When click once, then imageview has a border.
When click again, then imageview doesn't have a border.
How can I make that?
Thanks in advance!
Well you will need:
a PseudoClass for toggling the CSS state
a wrapping Region, because the ImageView itself does neither support a background nor a border.
A simple working example (the toggling of the PseudoClass is done with the help of a BooleanProperty, which is common practice and makes the management of its state easier):
#Override
public void start(Stage primaryStage) {
PseudoClass imageViewBorder = PseudoClass.getPseudoClass("border");
ImageView imageview = new ImageView(
new Image("http://upload.wikimedia.org/wikipedia/commons/1/16/Appearance_of_sky_for_weather_forecast,_Dhaka,_Bangladesh.JPG"));
BorderPane imageViewWrapper = new BorderPane(imageview);
imageViewWrapper.getStyleClass().add("image-view-wrapper");
BooleanProperty imageViewBorderActive = new SimpleBooleanProperty() {
#Override
protected void invalidated() {
imageViewWrapper.pseudoClassStateChanged(imageViewBorder, get());
}
};
imageview.setOnMouseClicked(ev -> imageViewBorderActive
.set(!imageViewBorderActive.get()));
BorderPane root = new BorderPane(imageViewWrapper);
root.setPadding(new Insets(15));
Scene scene = new Scene(root, 700, 400);
scene.getStylesheets().add(
getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
and the necessary CSS:
.image-view-wrapper:border {
-fx-border-color: black;
-fx-border-style: solid;
-fx-border-width: 5;
}

Resources