I have two layers in my program with different elements in each layer. The two layers are overlapping but the elements in the layers are not. I want to show a tooltip when the mouse hovers over a node in each layer but right now the top layer only gets the event.
Below is attached a minimal example:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
StackPane root = new StackPane();
Pane p1 = new Pane();
Pane p2 = new Pane();
Arc arc = new Arc(150,150,100,100,0,360);
arc.setType(ArcType.CHORD);
arc.setFill(null);
arc.setStroke(Color.BLUE);
arc.setStrokeWidth(20);
Rectangle rectangle = new Rectangle(100,100);
rectangle.setX(100);
rectangle.setY(100);
Tooltip.install(arc, new Tooltip("Semiring"));
Tooltip .install(rectangle,new Tooltip("Rectangle"));
p1.getChildren().add(arc);
p2.getChildren().add(rectangle);
root.getChildren().addAll(p2,p1);
primaryStage.setScene(new Scene(root, 300, 300));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Nothing happens on the rectangle
Use
p1.setPickOnBounds(false);
This essentially means mouse events are only delivered to p1 if the mouse is over a non-transparent pixel in p1. Thus when the mouse is not over the arc, mouse handling is delegated to p2, as required.
Related
I'm trying to achieve this effect here but on a static background (without the scrolling). I'm getting this weird clip on my results though (without the frost effect). I think I know where the problem is in my code but I'm not sure how to solve it.
public class App extends Application {
private static final double BLUR_AMOUNT = 80;
private static final Effect frostEffect = new BoxBlur(BLUR_AMOUNT, BLUR_AMOUNT, 3);
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
ImageView background = new ImageView(bgImage);
StackPane centerBlurredPane = (StackPane) frozenCenterUI();
BorderPane centerContent = new BorderPane();
centerContent.setCenter(new Text("Center"));
centerContent.setTop(new Text("Top"));
centerContent.setLeft(new Text("Left"));
centerContent.setRight(new Text("Right"));
centerBlurredPane.getChildren.add(centerContent);
Scene scene = new Scene(new StackPane(background,centerBlurredPane),414, 849);
primaryStage.setScene(scene);
primaryStage.show();
}
private Node frozenCenterUI() {
Image frostImage = background.snapshot(new SnapshotParameters(), null);
ImageView frost = new ImageView(frostImage);
Rectangle filler = new Rectangle(24, 762, 366, 696);
filler.setArcHeight(50);
filler.setArcWidth(50);
filler.setFill(Color.AZURE);
Pane frostPane = new Pane(frost);
frostPane.setEffect(frostEffect);
StackPane frostView = new StackPane(filler, frostPane);
Rectangle clipShape = new Rectangle(24, 762, 366, 696);
frostView.setClip(clipShape);
return frostView;
}
}
This is what i'm getting, however. I want to apply frost on the white area here.
What should my clip shape be?
Here's my background image, backgroundImage
Edit: I found that if I change my clipShape to have the same dimensions as the scene, then I get the desired effect. However, the BorderPane I added to the frozen pane is not constrained to it, but actually stretches and fills the entire window.
I am trying to create a simple splash screen. In fact I have a stackpane with an image as background. I do not want to show the default javafx decorations.
So I tried StageStyle.TRANSPARENT but it makes the whole thing transparent. On the other hand StageStyle.UNDECORATED show the image but with a white background. Here is the code in my start method.
public class SplashScreen extends Preloader {
private Stage stage;
#Override
public void start(Stage stage) throws Exception {
this.stage = stage;
StackPane root = (StackPane) FXMLLoader.load(getClass().getClassLoader().getResource("layouts/splash.fxml"));
Scene scene = new Scene(root, 690, 380,true, SceneAntialiasing.BALANCED);
scene.setFill(Color.TRANSPARENT);
stage.initStyle(StageStyle.TRANSPARENT);
stage.setScene(scene);
stage.show();
}
...
I am using java 11.0.8 and javafx 14
JavaFX 15 fixed this. Seems it was a bug.
Below there is a quick sample of a JavaFX application where the brown region (parent node) contains two child nodes, a red square and a blue circle. When I am reducing the width of the parent node to a size smaller than those of its children, I was expecting the child nodes to be partially visible. However, this is not the case but instead the child nodes are shown fully over parent's region. Any ideas on how to achieve that on the below example?
public class Test extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Parent Child Relationship!");
ParentNode parentNode = new ParentNode();
StackPane root = new StackPane();
root.getChildren().add(parentNode);
primaryStage.setScene(new Scene(root, 300, 250));
primaryStage.show();
}
}
class ParentNode extends Region {
private Rectangle square = new Rectangle();
private Circle circle = new Circle();;
public ParentNode() {
square.setWidth(40);
square.setHeight(40);
square.setFill(Color.RED);
circle.radiusProperty().bind(square.heightProperty().divide(3));
circle.centerXProperty().bind(circle.radiusProperty());
circle.centerYProperty().bind(square.heightProperty().divide(2));
circle.setFill(Color.BLUE);
circle.setStroke(Color.LIGHTGRAY);
getChildren().addAll(square, circle);
setBackground(new Background(new BackgroundFill(Color.CHOCOLATE, null, null)));
this.setMaxHeight(100);
this.setMaxWidth(200);
this.setMinHeight(0);
this.setMinWidth(0);
this.setOnMousePressed((e) -> this.setMaxWidth(20));
}
}
The only way i can think of, would be using a rectangle as the clip for the parentNode and binding its height and width to the parentNode's width and height properties, here is a working example:
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Parent Child Relationship!");
ParentNode parentNode = new ParentNode();
parentNode.maxWidthProperty().bind(primaryStage.widthProperty().subtract(200));
Rectangle clip = new Rectangle();
clip.widthProperty().bind(parentNode.widthProperty());
clip.heightProperty().bind(parentNode.heightProperty());
parentNode.setClip(clip);
StackPane root = new StackPane();
root.getChildren().add(parentNode);
primaryStage.setScene(new Scene(root, 400, 250));
primaryStage.show();
}
(i bound the parentNode's width to the windows width just so you see it working while you resize the window)
I have a javafx.scene.control.TableView containing some javafx.scene.control.TableColumns containing some javafx.scene.control.TextFields. Some of the TextFields should get a bi-coloured background: diagonally divided, the upper left half one colour, the lower right half another colour. Like the cells for Ge, Sb, Po in https://de.wikipedia.org/wiki/Periodensystem#/media/Datei:Periodensystem_deutsch_-_neue_Farben.svg. Is this possible without a background image?
Edit: added some code. For simplicity’s sake, i omitted the surrounding table and use now a javafx.scene.text.Text instead of a javafx.scene.control.TextField. The basic setup that follows gives a uniform background to the StackPane which is a start.
public class DividedBackgroundDemo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test: Diagonally divided colour background");
Text txt = new Text("Text");
txt.setFont(Font.font("Arial", FontWeight.BOLD, FontPosture.REGULAR, 50));
StackPane root = new StackPane();
root.getChildren().add(txt);
root.setStyle("-fx-background-color: blue;");
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Later on, when i will use a 13x13 grid of Text, i will have to imbed each Text into it’s own StackPane or another (perhaps more appropriate) subclass of Region to be able to provide an individually coloured background for each Text. And some of those Texts (especially the one in this example) should have a bi-colour background, both colours divided by the line from left bottom to right upper corner.
The simple solution would be to provide a background image. It’s not too difficult to produce one. But then, i have to produce a new background image for every pair of colours. I would prefer a more flexible solution.
All property setters and CSS properties i have found provide a one-colour-background. But sometimes i require bi-colour.
The proposed LineGradient would be acceptable if everything else fails. I would prefer a clear border between both colours, not a gradient.
Ok, i found a solution, at least for the simplified problem. Thanks to #kleopatra. As a path, i used a javafx.scene.shape.Polygon and filled it with the appropriate colour. Using aStackPane`, it is important to watch the z coordinate. Background naturally bottom, filled polyline as first content in the pane, and text on top.
public class DividedBackgroundDemo extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Test: Diagonally divided colour background");
Text txt = new Text("Text");
txt.setFont(Font.font("Arial", FontWeight.BOLD, FontPosture.REGULAR, 50));
Polygon triangle = new Polygon();
triangle.getPoints().addAll(new Double[] { 0.0, 0.0, 200.0, 0.0, 0.0, 200.0 });
triangle.setFill(Color.YELLOW);
StackPane root = new StackPane();
root.getChildren().add(triangle);
root.getChildren().add(txt);
root.setStyle("-fx-background-color: blue;");
primaryStage.setScene(new Scene(root, 200, 200));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Can you please tell me how can I realize that the whole content of a pane will be resized while the stage is resized with mousedragg. Here is my code:
public class fab extends Application {
private Stage stage;
private Pane pane;
private Scene scene;
#Override
public void start(Stage stage) throws Exception {
this.stage = stage;
Button button = new Button("Button");
pane = new Pane();
pane.getChildren().add(button);
stage.setTitle("Test");
scene = new Scene(pane, 640, 640);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
I think there is the idea of binding. But I don't know how to use that, in order to make all nodes of a pane resizable, when the stage size is changing.
I'm searching a solution without Fxml or sceneBuilder.
Thank you in advance.
If you insists to use the Pane container then after the line scene = new Scene(pane, 640, 640); add this:
scene.widthProperty().addListener((c,o,n)->button.setPrefWidth((Double)n));
scene.heightProperty().addListener((c,o,n)->button.setPrefHeight((Double)n));
and after the line stage.setScene(scene); add this:
button.setPrefSize(scene.getWidth(), scene.getHeight());
This works fine with Pane and do your required thing.
But I prefer using an AnchorPane container and set the Top, Right,Bottom and Left anchors to 0 .
Here is the solution if you wish to bind the width of the button to you scene width
button.minWidthProperty().bind(scene.widthProperty());
You can also modify this +/- whatever you want for ex
button.minWidthProperty().bind(scene.widthProperty().subtract(20));
and you can do the same for the height
button.minHeightProperty().bind(scene.heightProperty().subtract(200));