EDIT: SOLVED, ACCIDENTALLY FLIPPED X AND Y VALUES FOR LABEL'S 1 & 2
I'm creating an overlay using JavaFX, but for some reason two of my labels are missing while one is perfectly fine. It's weird because they all have the same y-value (setLayoutY) and only one label is successfully shown. When changing label 1's y-value from 536 to 500, it then gets show, but cut out.
When label 1's setLayoutY(536): http://i.imgur.com/M5NxQoa.png
When label 2's setLayoutY(500): http://i.imgur.com/heJDopx.png
It's weird because it's well within both the pane and stages size (by the way, which one takes precedence). On the other hand, label 2 has the same y-value of 536 and is displayed, but the rest aren't.
I really hope this isn't a simple mistake as I'm not seeing what I'm doing wrong. Why is this happening and how can I fix it? Thank you!
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.scene.paint.Color;
public class Overlay extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
Pane root = new Pane();
root.setPrefSize(765,596);
Label label1 = new Label("why does");
label1.setLayoutX(97);
label1.setLayoutY(536);
label1.setPrefWidth(57);
label1.setPrefHeight(184);
label1.setTextFill(Color.BLACK);
Label label2 = new Label("this happen");
label2.setLayoutX(481);
label2.setLayoutY(536);
label2.setPrefWidth(184);
label2.setPrefHeight(57);
label2.setTextFill(Color.BLACK);
Label label3 = new Label("-1");
label3.setLayoutX(289);
label3.setLayoutY(536);
label3.setPrefWidth(57);
label3.setPrefHeight(184);
label3.setTextFill(Color.BLACK);
root.getChildren().addAll(label1, label2, label3);
Scene scene = new Scene(root, 765, 596, Color.TRANSPARENT);
scene.setFill(Color.TRANSPARENT);
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.TRANSPARENT);
primaryStage.setAlwaysOnTop(true);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Set same PrefHeight in all label
label1.setPrefHeight(57);
label2.setPrefHeight(57);
label3.setPrefHeight(57);
Related
How can I create a popover like in the DatePicker class from javafx.scene.control.DatePicker as seen here:
The popover should when displayed be on top of all the other components as seen here (the popover is above the TextField):
Found a pretty simple solution to my problem, here is a code snippet in case people encounter the same problem
package main;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.Label;
import javafx.scene.control.MenuButton;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
BorderPane rootPane = new BorderPane();
MenuButton openButton = new MenuButton("Open Context Menu");
BorderPane contentPane = new BorderPane();
CustomMenuItem item = new CustomMenuItem(contentPane);
openButton.setStyle("-fx-selection-bar: transparent;"); //this is optional. it makes the blue background that appears when something is focused transparent
contentPane.setPrefSize(300, 300);
Label text = new Label("The ContextMenu will only close when you click the\nbutton below OR click outside of the ContextMenu.\nHow neat is that?");
text.setStyle(" -fx-text-fill: -fx-text-base-color;"); //needs to bet set if you want the selection-bar to be transparent. if not set the text will become invisible
contentPane.setTop(text);
Button closeButton = new Button("Close this popover");
closeButton.setOnAction(x -> {
openButton.hide();
});
contentPane.setBottom(closeButton);
item.setHideOnClick(false); // this will stop the ContextMenu from being hidden when clicking inside of it.
openButton.getItems().add(item);
rootPane.setCenter(openButton);
Scene scene = new Scene(rootPane, 550, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
}
I just placed a Pane with all of my content inside of a CustomMenuItem and added that CustomMenuItem to my MenuButton.
This above picture is result of my code.But I want like the following.
How can I fix it? The following is my code.I read too many sources but they was too complicated. For example,a source that I read, I think this way is very complicated.Maybe there is a easy way to solve this problem.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class Test extends Application {
public BorderPane border = new BorderPane();
public Label name = new Label("Name");
public Label surname = new Label("Surname");
public TextField name1 = new TextField();
public TextField surname1 = new TextField();
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage arg0) throws Exception {
Scene scene = new Scene(new VBox(), 300, 200);
arg0.setTitle("Header");
arg0.setResizable(false);
scene.setFill(Color.OLDLACE);
StackPane grid = addStackPane();
border.setMargin(grid, new Insets(12,12,12,12));
border.setCenter(grid);
((VBox) scene.getRoot()).getChildren().add(border);
arg0.setScene(scene);
arg0.show();
}
#SuppressWarnings("static-access")
public StackPane addStackPane() {
StackPane pane = new StackPane();
GridPane grid = new GridPane();
Label title = new Label("Border Title");
title.setStyle("-fx-translate-y: -7");
pane.setAlignment(title, Pos.TOP_LEFT);
grid.setStyle("-fx-content-display: top");
grid.setStyle("-fx-border-insets: 20 15 15 15");
grid.setStyle("-fx-background-color: white");
grid.setStyle("-fx-border-color: black");
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(25, 10, 25, 10));
grid.add(name, 1, 0);
grid.add(name1, 2, 0);
grid.add(surname, 1, 1);
grid.add(surname1, 2, 1);
pane.getChildren().addAll(grid, title);
return pane;
}
}
Thank you all that reads this topic.
Try to set -fx-background-color of your title label to the same color as the borderPane's background. And make sure you set in a css file, because it's not possible to set multiple styles via setStyle() unless you concatenate them:
myComponent.setStyle("-fx-text-fill: white;"+
"-fx-background-color: black;");
Furthermore it is bad practice to use an InlineStyleSheets as it always has a higher priority than a rule specified in a CSS StyleSheet.
(If you change pane.setAlignment(title, Pos.TOP_LEFT) to StackPane.setAlignment(title, Pos.TOP_LEFT) you can remove the "static-acces" warning.)
User jewelsea has made a control to perform this.
The related stackoverflow question is: How to add border to panel of javafx?
And on gitHub: https://gist.github.com/jewelsea/2838292
I have used it with minimal modification and it works like a charm.
I have a project in class where I need to display a traffic light with simply three cirlces. I started with the yellow one, and then attempted to add a red one in some random other place just to see if I could do it, however the yellow one is the only one showing. I can't tell if the red one is somehow underneath the yellow one, but in any case it doesn't make much sense to me as to why the red circle isn't showing.
package tryingGraphicsStuff;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.scene.paint.*;
import javafx.scene.text.*;
import javafx.scene.control.*;
public class TryingGraphicsStuff extends Application{
#Override
public void start(Stage stage) throws Exception {
// create circle
Circle circle = new Circle();
circle.setCenterX(150);
circle.setCenterY(150);
circle.setRadius(50);
circle.setFill(Color.RED);
// place on pane
StackPane p = new StackPane();
p.getChildren().add(circle);
// ensure it stays centered if window resized
//circle.centerXProperty().bind(p.widthProperty().divide(2));
//circle.centerYProperty().bind(p.heightProperty().divide(2));
Circle circleTwo = new Circle();
circleTwo.setCenterX(400);
circleTwo.setCenterY(400);
circleTwo.setRadius(50);
circleTwo.setFill(Color.YELLOW);
// place on pane
p.getChildren().add(circleTwo);
// create scene from pane
Scene scene = new Scene(p, 300, 1000);
// place scene on stage
stage.setTitle("Circle");
stage.setScene(scene);
stage.show();
}
public static void main (String [] args)
{
Application.launch(args);
}
}
A StackPane "lays out its children in a back-to-front stack". (The stack here is in z-coordinates). It is a "layout pane" which actually manages the placement of the child nodes for you. Consequently, the centerX and centerY properties of the circles are ignored, and they appear one on top of the other in the order they are added (so the red one is underneath the yellow one, and the only one you see is the yellow one). By default, the stack pane centers them.
All "layout panes" position the nodes for you. For example, a VBox will position nodes in a vertical stack, with the first one at the top, the second below, and so on. So if you used a VBox instead of a StackPane, the circles would appear one below the other (in the y-direction), but note they would still not respect the centerX and centerY properties.
The Pane class itself does not manage the layout of its child nodes; so if you want to use the coordinates for shape objects, Pane is probably your best option. Group behaves similarly, but takes on the bounds of the union of its child bounds, so it acts like Pane but its local coordinate system is different.
The following demo shows all these options. Again, Pane will be the one that behaves in an intuitive way.
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class CircleLayoutExample extends Application {
#Override
public void start(Stage primaryStage) {
TabPane tabs = new TabPane();
tabs.getTabs().add(createTab(new StackPane()));
tabs.getTabs().add(createTab(new VBox()));
tabs.getTabs().add(createTab(new Pane()));
tabs.getTabs().add(createTab(new Group()));
Scene scene = new Scene(tabs, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
private Tab createTab(Pane pane) {
Circle c1 = new Circle(150, 150, 50, Color.RED);
Circle c2 = new Circle(400, 400, 50, Color.YELLOW);
pane.getChildren().addAll(c1, c2);
Tab tab = new Tab(pane.getClass().getSimpleName());
tab.setContent(pane);
return tab ;
}
// annoyingly, Pane and Group do not have a common superclass with a getChildren()
// method, so just reproduce the code...
private Tab createTab(Group pane) {
Circle c1 = new Circle(150, 150, 50, Color.RED);
Circle c2 = new Circle(400, 400, 50, Color.YELLOW);
pane.getChildren().addAll(c1, c2);
Tab tab = new Tab(pane.getClass().getSimpleName());
tab.setContent(pane);
return tab ;
}
public static void main(String[] args) {
launch(args);
}
}
Yeah your both the circles are overlapping.
You can simply use a VBox instead of StackPane. It will solve your issue.
VBox p = new VBox();
As other answers have suggested, using a VBox would help you out the most here, since it will automatically put its children into a vertical row. Here is a brief snippet using an array (so you can make as many circles as you want)
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Circle;
import javafx.scene.paint.*;
public class TryingGraphicsStuff extends Application{
#Override
public void start(Stage stage) throws Exception {
Circle[] circle = new Circle[3]; // create 3 circles
VBox vBox = new VBox(); // vbox will put circles in vertical row
vBox.setAlignment(Pos.CENTER); // center circles
for(int i = 0; i < circle.length; i++){
circle[i] = new Circle(50); // initialize circles with radius of 50
vBox.getChildren().add(circle[i]);
}
circle[0].setFill(Color.RED);
circle[1].setFill(Color.YELLOW);
circle[2].setFill(Color.GREEN);
// add vbox to scene
Scene scene = new Scene(vBox, 300, 800);
stage.setTitle("Circle");
stage.setScene(scene);
stage.show();
}
public static void main (String [] args){
Application.launch(args);
}
}
As always, please understand the code and don't just mindlessly copy and paste. Cheers!
I'm actually a bit confused by the code above. According to your numbers the red one should be the one showing and not the yellow one. Your scene is only 300px wide and you center the yellow circle at 400 which will put it out of view (having a radius of only 50).
Either increase your scene size or move your circle inside your view.
When I run the following program
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Ellipse;
import javafx.stage.Stage;
public class Test1 extends Application {
public static void main(String[] args) throws Exception {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
Pane topPane = new Pane();
Scene scene = new Scene(topPane, 600, 400);
StackPane sp = new StackPane();
Label l1 = new Label("1 2");
Ellipse e1 = new Ellipse(100, 50);
e1.setOpacity(0.5);
sp.getChildren().addAll(l1, e1);
e1.radiusXProperty().bind(l1.widthProperty());
e1.radiusYProperty().bind(l1.heightProperty());
topPane.getChildren().add(sp);
sp.relocate(200, 100);
sp.setStyle("-fx-border-color: RED;");
Platform.runLater(() -> {
//l1.setText("123");
//l1.setText("1 2");
});
stage.setScene(scene);
stage.show();
}
}
I get a red box surrounding the text label only, but when I uncomment the two lines inside the Platform.runLater() block above, I get a red box surrounding the outer ellipse, which is what I want.
So it seems to me the layout bounds of the stack pane is not set correctly from the model description, since the bounds are determined only from the label control. But when I force an invalidation in Platform.runLater() the layout bounds are where they should be.
Why is this happening and how do I prevent it? I would like to be able to just specify my model/graph and then it should render correctly on the first show, or?
add this sp.requestLayout(); after stage.Show();
I have the following example code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("JavaFX Test");
GridPane grid = new GridPane();
grid.add(new Text("Enter the value in the text box below:"), 0, 0, 3, 1);
grid.add(new Text("Label: "), 0, 1);
grid.add(new TextField(), 1, 1);
grid.add(new Text("units"), 2, 1);
Scene scene = new Scene(grid);
primaryStage.setScene(scene);
primaryStage.sizeToScene();
primaryStage.show();
}
}
Which results in the following window:
If I resize the window to the width I would expect it to be, the TextField is also resized:
My question is, where is that white space on the right of the window coming from? Why is the window size so much wider than the space taken up by the components? Why is the TextField resized when I make my window smaller, even though the window has plenty of room for it?
If I remove the top Text, the window size is more sane:
I've tried using VBox and HBox to achieve the effect I'm looking for, but the window always seems to look like the first image above. What's going on?
This looks like a known bug: RT24636. It is fixed in the latest release (Java 1.8.0_05).
No workaround is posted on the JIRA and none comes to mind immediately.