My easy application has two layout panes. First is VBox pane. It is root node. Second pane is child pane (Pane layout). I want to use DropShadow effect for root pane only. I do it according to the documentation . Unfortunately I have the Drop shadow effect for both panes. For root and for child. Is it a bug or there is a way to set it for one pane only? I was trying to use pane.setEffect( null ) but without success. When I add some child to pane, the new node has shadow also.
I use JavaFX8 (Windows 7 - 64).
Thank you.
public void start( Stage stage )
{
VBox vbox = new VBox();
vbox.setPadding( new Insets( 30 ) );
BorderStrokeStyle style = new BorderStrokeStyle( StrokeType.INSIDE, StrokeLineJoin.MITER, StrokeLineCap.BUTT, 10, 0, null );
BorderStroke stroke = new BorderStroke( Color.BLUE, style, CornerRadii.EMPTY, new BorderWidths( 1 ), null );
vbox.setBorder( new Border( stroke ) );
DropShadow dropShadow = new DropShadow();
dropShadow.setOffsetX( 10 );
dropShadow.setOffsetY( 10 );
vbox.setEffect( dropShadow );
Pane pane = new Pane();
pane.setBorder( new Border( stroke ) );
pane.setPrefWidth( 500 );
pane.setPrefHeight( 500 );
vbox.getChildren().add( pane );
stage.setScene( new Scene( vbox ) );
stage.show();
}
addition:
Was trying to use css:
vbox.setStyle( "-fx-effect: dropshadow(gaussian, gray, 10, 0.6, 10, 10);" );
The same shit - the effect was applied for both panes. ((
Here I am trying to answer to my own question.
I made some easy investigations and It looks like it is not a bug. It is an attempt to provide a real life behavior for a pane.
If a pane doesn't have non-transparent background - the all pane's children should have a shadow also (if the owner pane has it). On the other hand - if the pane has solid background, the children can't have a shadow. Till you put shadow specially.
So... You just need to provide a non-transparent background for pane, to avoid shadows for pane's children shapes and panes.
Sure, It would be good to notice it in the docemtntation.
Related
So, the situation is... I have a vbox inside a scrollpane. I am adding hbox's into the vbox and then calling vbox.setVvalue(1.0) after every insert.
However say, there are 5 hbox's, the scroller only makes it so that the last visible item is the 4th hbox - with one hbox below what is currently seen(needing to be scrolled down to be visible).
I've found a solution which is to bind the scrollpane's vvalue property to the vbox's heightproperty like so: scrollPane.vvalueProperty().bind(vbox.heightProperty()) which i assume changes the vvalue to the max every time the vbox height is changed (i.e when a new hbox is added).
However, i still would like to improve my knowledge and why the first (setting the vvalue of the scrollpane after every insert) is different from binding the properties. Thanks!
Setting the new vvalue happens before the layout pass caused by modifying the VBox, but the result applied before the layout pass. Since the formula for the y coordinate of the top that are shown in the viewport is
top = max(0, vvalue * (contentHeight - viewportHeight))
and during the layout pass the content's top left is kept in place, you see the bottom of the old content at the bottom of the viewport.
To fix this you could manually trigger a layout pass on the ScrollPane using
scrollPane.applyCss();
scrollPane.layout();
Example
#Override
public void start(Stage primaryStage) {
VBox content = new VBox();
ScrollPane scrollPane = new ScrollPane(content);
VBox.setVgrow(scrollPane, Priority.ALWAYS);
Button button = new Button("fill");
button.setOnAction(evt -> {
for (int i = 0; i < 20; i++) {
content.getChildren().add(new Text(Integer.toString(i)));
}
System.out.println("content size before layout: " + content.getHeight());
// manually layout scrollPane
scrollPane.applyCss();
scrollPane.layout();
System.out.println("content size after layout: " + content.getHeight());
scrollPane.setVvalue(1d);
});
Scene scene = new Scene(new VBox(button, scrollPane), 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
I am trying to change the brightness of the whole scene in javafx. This is what my code looks like at the moment:
public void start(Stage primaryStage) {
StackPane root = new StackPane();
Rectangle rec1 = new Rectangle();
rec1.setWidth(300);
rec1.setHeight(300);
rec1.setFill(javafx.scene.paint.Color.RED);
ColorAdjust colorAdjust = new ColorAdjust();
colorAdjust.setBrightness(-0.8);
root.setEffect(colorAdjust);
Scene scene = new Scene(root, 1920, 1080);
root.getChildren().add(rec1);
primaryStage.setFullScreen(true);
primaryStage.setScene(scene);
primaryStage.show();
}
The problem is, like this only the brightness of the rectangle changes, but not the brightness of the whole scene. I also need to change the brightness of the "background". Is there any way to do that?
Strangely this seems to be fixed by adding a node to the StackPane in order for it to adjust the color to everything, not just shapes. When shapes are the only thing visible, that is all that's ColorAdjusted. At least one Node must be present. Changing the one line to the following will do what you want:
root.getChildren().addAll(rec1, new Label());
However, this could have consequences to your project by shift something slightly even though it's empty. We can get around this by making it invisible and not-managed so that it isn't considered in layout calculations.
Label fix = new Label("Fix colorAdjust whole scene.");
fix.setVisible(false);
fix.setManaged(false);
Scene scene = new Scene(root, 500, 500);
root.getChildren().addAll(rec1, fix);
I am having problems with positioning my images in my JavaFX program using setX and setY on the ImageView's for the images. I am not sure what is the problem? Appreciate any help given!
Here's my code:
Image rocket2 = new Image("img/Rocket.png");
ImageView iv1 = new ImageView(rocket2);
iv1.setX(60);
iv1.setY(44);
Image rocket1 = new Image("img/Rocket.png");
ImageView iv2 = new ImageView(rocket1);
iv2.setX(5);
iv2.setY(16);
Image background = new Image("img/space.png");
ImageView iv3 = new ImageView(background);
StackPane root = new StackPane();
root.getChildren().addAll(iv3, iv2, iv1);
Scene scene = new Scene(root, 300, 300);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.setTitle("Space stuff");
primaryStage.show();
I suspect that something goes wrong because I have set a background image.
img here on what's happening
Don't place your items in a StackPane if you want to explicitly define their layout positions (setX and setY). A StackPane is a managed layout pane. It will automatically set the location of items added to it (default is to center everything one on top of the other inside the StackPane).
Instead use a Pane or a Group, which are not managed layout panes and allow you to layout your content in the Pane however you wish.
To layout your content inside the Pane, you can use setLayoutX and setLayoutY rather than setX and setY, though I guess setX and setY should also work (I've never used them before on ImageView).
Pavlo, already created an answer while I was typing this (so this answer is a duplicate), but I'll leave this as it adds a bit more explanation.
Replacing StackPane with Pane should solve the problem.
If you however want for whatever reason to position a item in a StackPane you can use setTranslateX and setTranslateY. Theese methods set the x and y values AFTER the StackPane has done its layouting, so you will have a different starting position depending on the Alignment your StackPane uses for its children.
I am new to JavaFX (been working with swing for a long time) and am trying to work with BorderPane. One would assume BorderPane is similar to BorderLayout but the big difference is the center of BorderPane will expand to fit its contents while BorderLayout will shrink to fit the window.
I am using JFXPanel in a JFrame and have a 3 part interface: A panel on the left (some text), some buttons on the bottom (flow control), and in the center want to have a dynamic panel/pane, that for the most part will be just an imageview. I set it all up and it works fine, but I'm working with camera images here which are way bigger than my monitor. I've tried scaling the images down by binding the imageview width to different things (such as anchor pane, scene size (works, but not properly), etc. The issue I am having is that since borderpane's center panel expands to fit its content, it will expand and never have a proper value I can bind to. I need the image to be fully visible in the window at any size.
Here's the code I've been working with.
protected void setupFXWindow(JFXPanel mainPanel) {
butNext = new Button("Next Step");
butBack = new Button("PreviousStep Step");
butQuit = new Button("Cancel Signature Generation");
butNext.setTooltip(new Tooltip("Next step..."));
butBack.setTooltip(new Tooltip("Previous Step..."));
butQuit.setTooltip(new Tooltip("Quit generating a signature"));
Group root = new Group();
Scene scene = new Scene(root, javafx.scene.paint.Color.ALICEBLUE);
javafx.scene.image.Image fximage = new javafx.scene.image.Image(new File(image.getSourceFilePath()).toURI().toString());
ImageView iv1 = new ImageView();
iv1.setImage(fximage);
iv1.setPreserveRatio(true);
VBox directionsPanel = new VBox();
HBox authorflowPanel = new HBox(); //bottom buttons for next, back, etc.
mainPanel.setScene(scene);
//INSTRUCTIONS
directionsStepLabel = new Text();
directionsLabel = new Text();
setDirectionsText("Directions will be placed here.");
exampleLabel = new Text("Example");
exampleIconLabel = new Text("An example image will be shown here.");
directionsPanel.setPadding(new javafx.geometry.Insets(5, 5, 5, 5));
directionsPanel.getChildren().addAll(directionsStepLabel, directionsLabel, exampleLabel);
authorflowPanel.getChildren().addAll(butBack, butQuit, butNext);
BorderPane bp = new BorderPane();
bp.prefHeightProperty().bind(scene.heightProperty());
bp.prefWidthProperty().bind(scene.widthProperty());
bp.setLeft(directionsPanel);
bp.setBottom(authorflowPanel);
bp.setCenter(iv1);
root.getChildren().add(bp);
}
This code sample doesn't have iv1 (imageview) binded to anything, cause at this point I have no idea what I can bind to that will give me the remaining space in the scene. Since I cannot use the full width or height of the scene, I'm at a loss of what I am supposed to do here.
The code above makes it look like this:
Wrap the ImageView in some kind of Pane (e.g. a StackPane). Then the pane will fill the center region of the border pane and you can bind to its width and height:
ImageView iv1 = new ImageView();
iv1.setImage(fximage);
iv1.setPreserveRatio(true);
StackPane imageContainer = new StackPane(iv1);
iv1.fitWidthProperty().bind(imageContainer.widthProperty());
iv1.fitHeightProperty().bind(imageContainer.heightProperty());
// ...
bp.setCenter(imageContainer);
I have a stackpane. When I add a second item to my stack pane, both show up, but I can't click on my first item anymore. It becomes 'unclickable'.
what ever I defined in my .setonmouse does not work. It works for my second item. If I switch the order they are in the stack pane, the other one works, but not both.
is there a fix for this? This is what my program looks like:
I want my 'grid' centered ALWAYS. There are buttons to the left centered in a column, there will be buttons on the right later on, and there will be buttons/Text on top of the grid and buttom in the margins later on too.
I want everything to be clickable.
http://img688.imageshack.us/img688/6025/examplerg.png
StackPane orders items in Z-order: latter above the former. So, your second item gots all mouse clicks and first one (being covered by second) doesn't get anything.
For layout you've described you can use BorderPane:
public void start(Stage stage) throws Exception {
BorderPane root = new BorderPane();
root.setCenter(new Rectangle(100,100, Color.RED));
root.setLeft(new Rectangle(10,10, Color.BLUE));
root.setRight(new Rectangle(10,10, Color.CYAN));
stage.setScene(new Scene(root,300,300));
stage.show();
}
You can make any Pane "mouse transparent", so that it doesn't consume any click events, and lets them pass through to the stack under it.
Here's some example code... this example sets up 4 panes in a stack, with just the mainPane accepting clicks to begin with.
StackPane rootPane = new StackPane();
VBox mainPane = new VBox(80);
BorderPane helpOverlayPane = new BorderPane();
helpOverlayPane.setMouseTransparent(true);
Canvas fullScreenOverlayCanvas = new Canvas();
fullScreenOverlayCanvas.setMouseTransparent(true);
VBox debugPane = new VBox();
debugPane.setAlignment(Pos.BASELINE_RIGHT);
AnchorPane debugOverlay = new AnchorPane();
debugOverlay.setMouseTransparent(true);
debugOverlay.getChildren().add(debugPane);
AnchorPane.setBottomAnchor(debugPane, 80.0);
AnchorPane.setRightAnchor(debugPane, 20.0);
rootPane.getChildren().addAll(mainPane, fullScreenOverlayCanvas, debugOverlay, helpOverlayPane);
Now, when you want to use your canvas to draw on top, make sure you change mouse transparent to false for just that stack, and keep all panes on top of it mouse transparent.
fullScreenOverlayCanvas.setMouseTransparent(false);
debugOverlay.setMouseTransparent(true);
fullScreenOverlayCanvas.setVisible(true);
doSomethingWithCanvasThatNeedsMouseClicks();
P.S. I did some editing of the code I had, so it may not run as-is. Also, see discussion of making only parts of panes transparent here:
JavaFX Pass MouseEvents through Transparent Node to Children