JavaFX undecorated Window with shadow - javafx

I am trying to figure out, how to create an undecorated window with its regular shadow behaivor (like for all windows when using Windows).
I read several articles but non of them really worked.
As far as I understood, I have to create the main stage with some kind of padding. This stage has to have a transparent background. The actual content needs to be placed on some kind of other node.
So I took a stackpane for my root element and placed a vbox on it. The vbox should by the actual main stage area (I colored that area in green).
But I tried to use the StageStyle to transparent, I tried to fill out the stackpane with a transparent background but non of them worked. Also the shadow doesn't work as expected (I removed the shadow experiment in my example).
private void createPopup2() {
StackPane stackePane = new StackPane();
VBox rootPane = new VBox();
rootPane.setStyle("-fx-background-color: green; -fx-border-color: black; -fx-border-width: 1px;");
stackePane.getChildren().add(rootPane);
stackePane.setPadding(new Insets(20, 20, 20, 20));
Scene scene = new Scene(stackePane);
final Stage stage = new Stage();
stage.initStyle(StageStyle.TRANSPARENT);
stage.setWidth(600);
stage.setHeight(350);
stage.setScene(scene);
stage.initModality(Modality.APPLICATION_MODAL);
stage.show();
}
I am quite confused and have no idea how to fix that.

Firstly I am not sure what type of shadow you are expecting. It will be helpful if you can provide the example for shadow you tried, so that we may know the actual issue.
Having said that, have you tired using -fx-effect on VBox.? The below code creates a shadow effect around the green box.
StackPane stackePane = new StackPane();
stackePane.setStyle("-fx-background-color:transparent");
VBox rootPane = new VBox();
rootPane.setStyle("-fx-background-color: green; -fx-border-color: black; -fx-border-width: 1px;-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, .75), 20, 0.19, 0, 0);");
stackePane.getChildren().add(rootPane);
stackePane.setPadding(new Insets(20, 20, 20, 20));
Scene scene = new Scene(stackePane, Color.TRANSPARENT);
final Stage stg = new Stage();
stg.initStyle(StageStyle.TRANSPARENT);
stg.setWidth(600);
stg.setHeight(350);
stg.setScene(scene);
stg.initModality(Modality.APPLICATION_MODAL);
stg.show();
You can tweak the parameters of the drop-shadow to get your desired effect.
The doc related to parameters is as below :

Related

JavaFX Layout issue within hbox

I want to add an statusbar to my application (the root pane is a vbox and the statusbar is a hbox with a fix height). On this statusbar I have a label with something like "2 processes running". As soon as the mouse hoovers this label, I want to add a Pane above this label with some details about the processes (like IntelliJ or Eclipse).
My problem in the moment is how to create this pane and position this pane above the label.
I create a simple example of my problem
The green area is a StackPane on the root VBox with VGow = Always. The red area is the Hbox with a fix height of 30 pixel. Then I added the yellow VBox the the HBox and put the minHeight to 300.
The problem is, that the yellow area should be above the red area (over the green area) and not outside the window.
What is the best way to achive something like that?
The only way I figured out was using a negative top margin amount (- max/min height). But then the window gets stretched because the yellow pane (or the green bordered pane is not on top of the other elements). The red crossed area shouldn't be there. The green boxed area should be above the other content. Probably I can't use a vbox as my root element?
Update 1
Here is an example - strange thing is, that it is working in this standalone example. But is that the way I should do something like that?
VBox rootBox = new VBox();
rootBox.setMaxHeight(500);
rootBox.setStyle("-fx-background-color: lightgreen");
StackPane contentPane = new StackPane();
contentPane.getChildren().add(new Button("Dont click me"));
contentPane.setStyle("-fx-background-color: lightblue");
VBox.setVgrow(contentPane, Priority.ALWAYS);
HBox statusbar = new HBox();
statusbar.setMinHeight(30);
statusbar.setMaxHeight(30);
statusbar.setStyle("-fx-background-color: red");
VBox processIndicatorBox = new VBox();
processIndicatorBox.setMinHeight(30);
processIndicatorBox.setMaxHeight(30);
HBox.setMargin(processIndicatorBox, new Insets(-300, 0, 0, 0));
StackPane processListPane = new StackPane();
processListPane.setStyle("-fx-background-color: yellow");
processListPane.setMinHeight(300);
processListPane.setMaxHeight(300);
processListPane.setMinWidth(150);
processListPane.setMaxWidth(150);
processListPane.setVisible(false);
Label label = new Label("Show processes");
label.setOnMouseEntered(mouseEvent -> processListPane.setVisible(true));
label.setOnMouseExited(mouseEvent -> processListPane.setVisible(false));
processIndicatorBox.getChildren().addAll(processListPane, label);
statusbar.getChildren().add(processIndicatorBox);
rootBox.getChildren().addAll(contentPane, statusbar);
Scene scene = new Scene(rootBox, 600, 500);
primaryStage.setScene(scene);
primaryStage.show();
Many greetings
Hauke
Did you consider using GridPane? ( https://docs.oracle.com/javase/8/javafx/api/javafx/scene/layout/GridPane.html ). Gives you more control to layout elements with different sizes. VBox and HBox are from my experience good when all elements have similar sizes.
Here a pseudo-pseudo code
GridPane grid = new GridPane();
Pane greenBox = new Pane(); //your green box
Pane redBox = new Pane(); //your red box
Pane yellowBox = new Pane(); //your yellow box
// add the panes to the grid pane and define where they are
grid.add(greenBox, 0, 0); set the green box in column 0 and row 0
grid.add(redBox, 0, 1); set the red box in column 0 and row 1
grid.add(yellowBox, 1, 1); set the yellowbox in column 1 and row 1
// size of the boxes
GridPane.setColumnSpan(greenBox,2); //The green box should span over 2 columns
GridPane.setRowSpan(yellowBox,2); //The red box should span over 2 rows
The boxes are now only empty panes, which will have a minimum size without content. Replace the Pane() boxes with the content you want to put in or put the content in the Pane() objects.

JavaFX 3D boxes overlapping each other

I am having a problem with JavaFX 3D, the problem is as follows:
When I turn my perspective camera around, the last added box (blue box) overlaps the first added box (red box), here is a screenshot:
can anyone tell me why is this happening? And is there a way to fix it? (the boxes are literally 2 box classes with a width, height, depth, position and color)
Minimal reproducible example since somebody asked for it:
Box box1 = new Box();
Box box2 = new Box();
box1.setWidth(300);
box2.setWidth(300);
box1.setHeight(300);
box2.setHeight(300);
box1.setDepth(300);
box2.setDepth(300);
box1.setTranslateX(300);
box2.setTranslateX(300);
box1.setTranslateY(300);
box2.setTranslateX(300);
Group root = new Group();
root.getChildren().addAll(box, box2);
PerspectiveCamera cam = new PerspectiveCamera();
Scene scene = new Scene(root);
scene.setCamera(camera);
stage.setScene(scene);
stage.show();
where stage is the stage inside public void start(Stage stage), JavaFX's default run method (any class that extends Application should implement it)
You probably have to add a subscene with the depth buffer enabled. See: https://openjfx.io/javadoc/15/javafx.graphics/javafx/scene/SubScene.html#%3Cinit%3E(javafx.scene.Parent,double,double,boolean,javafx.scene.SceneAntialiasing)
Solution:
I used the following constructor:
new Scene(root, WIDTH, HEIGHT, true, SceneAntialiasing.BALANCED);
instead of:
new Scene(root);

JavaFx sizing layouts

I'am not familiar with JavaFx so I'am trying to code my JavaFx Components in Java Controller classes and calling them in main, my problem is that I cant size my layouts with all the width of the the window, I have this simple code :
public Acceuil(){
LAB_POST = new Button("Posts");
LAB_EVENT = new Button("Evennements");
.....
// my two boxes
VBox leftPane = new VBox();
FlowPane bpane = new FlowPane();
leftPane.setPadding(new Insets(20));
leftPane.setSpacing(30);
leftPane.setAlignment(Pos.CENTER);
leftPane.setStyle("-fx-background-color:#34495e");
leftPane.setMinWidth(300);
leftPane.setPrefSize(300, 600);
bpane.setStyle("-fx-background-color: red;"); // to see the space that it took
bpane.setMaxWidth(Double.MAX_VALUE);
bpane.setMaxWidth(Double.MAX_VALUE);
bpane.setMaxWidth(Double.MAX_VALUE);
bpane.setMaxWidth(Double.MAX_VALUE);
leftPane.getChildren().addAll(TXT_SEARCH, LAB_POST....);
this.getChildren().addAll(leftPane,bpane);
this.setMinHeight(600);
this.setMinWidth(900);
}
(Ps: I tried the FlowPane,BorderPane,AnchorPane and even Boxes)
So I'am Expecting to have the bpane in all the space that remains in my window but I get this,
So I'am wondering what I need to type to let the bpane take all the space, Thank you
I agree with Sedrick we need to know what is the container of these elements but you can try this:
bpane.setStyle("-fx-background-color: red;");
HBox.setHgrow(bpane, Priority.ALWAYS); // Add this line
Also if it is inside an AnchorPane you can try this:
AnchorPane.setTopAnchor(this, 0.0);
AnchorPane.setRightAnchor(this, 0.0);
AnchorPane.setBottomAnchor(this, 0.0);
AnchorPane.setLeftAnchor(this, 0.0);

Spinner within gridpane has strange resize effects

My goal is to have a GridPane where every item is grown to its max size. When I use the Spinner component, however, there are some unexplainable resize effects: whenever the Spinner component gets focus, or the value changes, it grows a bit, until the other component is on its minimum size.
Code snippet:
ChoiceBox<String> box1 = new ChoiceBox<>();
box1.getItems().add("Item 1");
box1.setMaxWidth(Double.MAX_VALUE);
Spinner spinner = new Spinner(1, 365, 1);
spinner.setMaxWidth(Double.MAX_VALUE);
GridPane gridPane = new GridPane();
gridPane.setHgap(5);
gridPane.setVgap(5);
gridPane.setPadding(new Insets(5));
gridPane.addRow(0, box1, spinner);
GridPane.setHgrow(box1, Priority.ALWAYS);
GridPane.setHgrow(spinner, Priority.ALWAYS);
Scene scene = new Scene(gridPane, 1000, 400);
primaryStage.setTitle("Spinner in GridPane");
primaryStage.setScene(scene);
primaryStage.show();
Can anyone explain me why this is happening and how I can get rid of it?
According to the JDKBug, it is fixed and going to be available in JAVA9

JavaFX: Making BorderPane's Center's contents not strech

just a quick one for you since I'm generally inexperienced in designing apps. Any help would be greatly appreciated.
I've got the following application, and it's obvious that it uses a BorderPane for its layout. I've got a GridPane of 5 labels and 5 textFields in the Center region, and I wanted a subtle border for it.
As you can see, the GridPane utilizes the full space allocated to it in the Center region, and although the border gets drawn nicely, it goes all the way down to the bottom of the Center region (Red arrows).
What I want it to do is finish at the blue line.
I tried using grid.setPrefHeight(400);, for example, but it didn't work.
Are there any solutions other than the obvious one, to add a second container below the GridPane and squeeze the upper container enough?
EDIT: For reference, this is the code that creates the center area GridPane:
public GridPane addGridPaneCenter() {
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(0, 10, 0, 10));
sihuid = new Text("SIHU ID:");
sihuid.setFont(Font.font("Inconsolata", 16));
grid.add(sihuid, 0, 1); //spans from 0,1 to 1,1 (Column-Row)
sihuid_tf = new TextField();
sihuid_tf.setEditable(false);
grid.add(sihuid_tf, 1, 1);
mac = new Text("Plug MAC:");
mac.setFont(Font.font("Inconsolata", 16));
grid.add(mac, 0, 2);
mac_tf = new TextField();
mac_tf.setEditable(false);
grid.add(mac_tf, 1, 2);
loc = new Text("Location:");
loc.setFont(Font.font("Inconsolata", 16));
grid.add(loc, 0, 3);
loc_tf = new TextField();
loc_tf.setEditable(false);
grid.add(loc_tf, 1, 3);
appl = new Text("Appliance:");
appl.setFont(Font.font("Inconsolata", 16));
grid.add(appl, 0, 4);
appl_tf = new TextField();
appl_tf.setEditable(false);
grid.add(appl_tf, 1, 4);
type = new Text("Type:");
type.setFont(Font.font("Inconsolata", 16));
grid.add(type, 0, 5);
type_tf = new TextField();
type_tf.setEditable(false);
grid.add(type_tf, 1, 5);
grid.setPrefHeight(400);
grid.setStyle(
"-fx-border-color: #b8b8ba; -fx-border-width: 1;"
+ "-fx-border-radius: 4;"
/*+ "-fx-font: " + "Inconsolata" + ";" */
);
return grid;
}
After that, there's a simple
GridPane grid_center = addGridPaneCenter(); //CENTER Grid, contains info about plugs.
border_pane.setCenter(grid_center);
Scene scene = new Scene(border_pane, 900, 700);
scene.setFill(Color.GHOSTWHITE);
primaryStage.setTitle("PlugControl v0.1e");
primaryStage.setScene(scene);
primaryStage.show();
I'm afraid this is behaviour of BorderPane is by design (ref):
The top and bottom children will be resized to their preferred heights and extend the width of the borderpane. The left and right children will be resized to their preferred widths and extend the length between the top and bottom nodes. And the center node will be resized to fill the available space in the middle.
You should probably put the GridPane in an AnchorPane or VBox and put that (AnchorPane or VBox) in the center of the BorderPane.

Resources