UNIFIED StageStyle and Transparent Scene produce black background instead of transparent - css

JavaFX 8 has StageStyle.Unified, enabling to create OS X style, unified toolbars. I have tested the following code works correctly in JDK 8u5.(the scene background is transparent and the button appears against the stage background.)
However in JDK 8u25 and JDK 8u31 there is a weird behavior. the scene background becomes black.
changing the scene color to anything other than transparent works fine, it displays that color.
It is looking like a bug to me unless I am missing something,
Any ideas?
public class UnifiedTest extends Application {
#Override
public void start(Stage primaryStage) {
StackPane testPane = new StackPane();
testPane.setStyle("-fx-background-color:transparent;");
Label someText = new Label("TEXT AGAINST TRANSPARENT SCENE");
testPane.getChildren().add(someText);
Scene myScene = new Scene(testPane,500,500);
myScene.setFill(Color.TRANSPARENT);
primaryStage.setScene(myScene);
primaryStage.initStyle(StageStyle.UNIFIED);
primaryStage.setTitle("Application");
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Some more information:
By stage background I meant the background of the window that is provided by the OS.
I am trying to create a unified toolbar. According to JavaFX 8 API the way to do it is to use StageStyle.UNIFIED. this will give a window provided by the OSX.
It looks like this when there is no scene added:
http://imgur.com/iHEiVf0,fMbFr4e,bFSL8bA
However when I setFill(Color.TRANSPARENT) the scene background becomes black:
http://imgur.com/iHEiVf0,fMbFr4e,bFSL8bA#2
The desired result is to see the text against the background of the first link. It worked with JDK 8u5, but now I am using 8u31 and instead of that grey I get black. What is weird is that if I setFill(Color.RED) the background becomes red as expected
From the JavaFX 8 api:
public static final StageStyle UNIFIED
Defines a Stage style with platform decorations and eliminates the border between client area and decorations. The client area background is unified with the decorations. This is a conditional feature, to check if it is supported see Platform.isSupported(javafx.application.ConditionalFeature). If the feature is not supported by the platform, this style downgrades to StageStyle.DECORATED
` NOTE: To see the effect the Scene covering the Stage should have Color.TRANSPARENT

Looks like this is a bug, which is fixed for Java 8u60:
JDK-8095040 StageStyle.UNIFIED not working on OSX 10.9.5
Kevin Rushforth comments on the bug tracker:
It looks like the regression was introduced some time in 8u20.

Related

JavaFX - "Pointless" (CSS) Shadow Effect, Drastically decrices Graphics Performance

Hello, People [...]
🤔 Summary
Whenever i use Shadow-effect on my BorderPane or any Component/control/Element, the 3D Graphics performance (as seen, in the Preview section below) is getting way too low.
The "confusing" part is that, it even gets low performance when the effect is applied to something that really has nothing to do with my Tab, Subscene or even my moving Button, in a way [...]
I Use jdk-12.0.1.
👁️ Preview
⚠️ Recreating The Issue
Files Needed:
App.java | main.fxml | AnchorPane.css | MathUtils.java | SimpleFPSCamera.java
📝 General Code
(You can refer to Recreating The Issue Section for more Informations too)
AnchorPane.css
#BorderPane1 {
-fx-effect: dropshadow(three-pass-box, rgb(26, 26, 26), 50, 0.6, 0, 0); /* Comment it*/
}
App.java
public class App extends Application {
#FXML
public Parent root;
public TabPane TabPane1;
public BorderPane BorderPane1;
public static void main(String[] args) throws Exception {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml"));
loader.setController(this);
root = loader.load();
Scene RootScene = new Scene(root, 1120, 540);
primaryStage.setScene(RootScene);
Thread t = new Thread() {
public void run() {
//Setting NewButton2
Button NewButton2 = new Button();
NewButton2.setId("Button2");
NewButton2.setText("test2");
NewButton2.setPrefWidth(150);
NewButton2.setPrefHeight(50);
NewButton2.setTranslateX(-75);
NewButton2.setTranslateY(-25);
NewButton2.setTranslateZ(900);
// Setting group
Group SubRootGroup = new Group(NewButton2);
SubRootGroup.setTranslateX(0);
SubRootGroup.setTranslateY(0);
SubRootGroup.setTranslateZ(0);
// Setting Scene
SubScene SubScene1 = new SubScene(SubRootGroup, 0, 0, true, SceneAntialiasing.BALANCED);
SubScene1.setId("SubScene1");
SubScene1.setFill(Color.WHITE);
SubScene1.heightProperty().bind(RootScene.heightProperty());
SubScene1.widthProperty().bind(RootScene.widthProperty());
// Initializing Camera
SimpleFPSCamera SimpleFPSCam = new SimpleFPSCamera();
// Setting Camera To The Scene
SubScene1.setCamera(SimpleFPSCam.getCamera());
// Adding Scene To Stage-TabPane.Tab(0)
TabPane1.getTabs().add(new Tab("Without Shadows"));
TabPane1.getTabs().get(0).setContent(SubScene1);
// Loading Mouse & Keyboard Events
SimpleFPSCam.loadControlsForSubScene(SubScene1);
}
};
t.setDaemon(true);
t.run();
primaryStage.show();
}
}
Things I 've Tried Until Now
javafx animation poor performance consumes all my cpu
setCache(true);
setCacheShape(true);
setCacheHint(CacheHint.SPEED);
(i have tried using it with all components without having any success [it might be my poor javaFX knowledge too , [using it in the wrong way?] ])
...
💛 Outro
Any Idea? Thanks In Advance, Any help will be highly appreciated, 💛 [...]
George.
Most probably, you will have figured this out by now, but since I was also banging my head about this same issue in the past, here is your answer:
The drop shadow effect is "expensive" and drawing it is slow. If you use it on a node with many descendants and move any of the descendants, it will cause the effect to be re-calculated on the parent, so the whole animation becomes slow (regardless if the parent itself is animated or not).
I solved this by using a StackPane as the top-most container, to which I added a Pane as a first child (which has the css drop-shadow effect) and the normal top-level container for the actual controls as a second child.
This way, the "shadow" pane is not updated when something is animated down the layout tree and, voila, you have a working drop-shadow effect without a performance hit :-)

Why does the application window only have a top and left inner border and how to do fix it?

After working with JavaFX applications on a daily basis for about one and a half year, I just recently noticed that the application window only has a inner border (the border separating the frame from the content inside the stage) on the top and left side of the window. And now when I've seen it, I can't unsee it.
Here's an MCVE displaying a empty application window:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class MCVE extends Application {
#Override
public void start(Stage stage) {
AnchorPane pane = new AnchorPane();
stage.setScene(new Scene(pane, 800, 800));
stage.show();
}
public static void main(String[] args) {
launch();
}
}
And here's the result:
If you zoom in you can clearly see what I mean:
Why is it designed like that? To me, it looks really weird. I'd like the window to have an inner border on all four sides, but maybe I'm missing some design principle here or something.
And how would I change the style of the application window so it has all four borders if I wanted to? The closest I could get was to set primaryStage.initStyle(StageStyle.UNIFIED); and then style the border of the window content pane instead. But the problem with this approach is that the standard inner border replicates the look of the outer border of the window, and just setting a custom border on the content pane somehow made it hard to replicate the style of the outer border perfectly. Either it looked too sharp or too blurry, or the color was wrong.

When full screen is applied in javaFx the controllers doesnt adjust to the screen

Im doing my 1st JavaFx project using scene builder 2.0. When I set the fullscreen method true, the anchor pane goes to full screen but the controllers inside the container doesn't adjust according to the adjusted pane size. It will be a great help if someone could point me out where I have messed up.
This is the code I have used in the main program.
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
javafx.geometry.Rectangle2D r = Screen.getPrimary().getBounds();
Scene scene = new Scene(root,r.getWidth(), r.getHeight());
String css = this.getClass().getResource("newCascadeStyleSheet.css").toExternalForm();
stage.setScene(scene);
scene.getStylesheets().add(css);
stage.show();
}
Ive set the sizes padding and everything using scene builder options.
Thanks in advance.
I think what you are missing is a Fit to parent setting in your view.
As you are using SceneBuilder, I suggest you to try the following: in the Hierarchy view (left side) right-click your component and select Fit to parent.
This is an example (taken from this awesome tutorial):

Resize a Button JavaFX

i have a question about a JavaFx Button.
In the following code i add a Button into a HBox.
ivTriangleImg.setFitHeight(16);
ivTriangleImg.setFitWidth(16);
ivTriangleImg.setRotate(iRotateCoord1);
btnTriangle.setGraphic(ivTriangleImg);
btnTriangle.setStyle("-fx-background-color:green;");
addComponentToBox(btnTriangle);
The Button gets a Graphic -> The Graphic is a transparent triangle with the Size of 16x16 pixels.
The Problem is, that the Button doesn't have the Size 16x16 it is so much more. How can i get the Button smaller and the Pictur must have the same size?
For JavaFX 8 use
btnTriangle.setPadding(Insets.EMPTY);
For JavaFX 2 use
btnTriangle.setStyle("-fx-padding: 0;");
However you can directly put the image view to the scene rather than setting it to the button's graphic, and add listeners you want:
ivTriangleImg.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
// do something
}
});
I added your Code, it works very fine. I made it a little bit different:
btnTriangle.setStyle("-fx-background-color:transparent;-fx-padding:0;-fx-background-size:0;");

How do you create a rounded border with a semi transparent background for a button in JavaFX?

I want to create buttons like this in JavaFX (not html).
http://jsfiddle.net/x7dRU/3/
(hover on them to see the effect)
[Stupid Stackoverflow insists on me posting jsfiddle code here which isn't relevant]
<li>Button 1</li>
So with a rounded border and a transparent background. Unfortunately the background/insets technique seems to overwrite the content from outside to in. So if you draw a bright border, then you can't undo the brightness to create a dark&transparent background without hardcoding the colour. I.e. it's not write once, run everywhere, on different coloured panels.
-fx-border-color doesn't seem to support rounding or at least isn't recommended here Set border size . I imagine the rounding of the border doesn't sync with the rounding of the background.
Seems HTML5 has the edge on this one then. Tell me I'm wrong :-) ...although I suspect my question can't be done without specifying the colour for each and every button context.
Browny points.
Note, I realise I've coloured the white border greenish (context sensitive), I'm happy with a border of semi-transparent white as a solution. First prize would be a burn/dodge/etc(background-colour) function ala photoshop.
Plan B.
It doesn't look so bad without rounded edges, so maybe I should just resort to -fx-border-color
Background info
Have a look at the information in the css documentation on "looked-up colors"(scroll down a little, beyond the named color section).
The way these basically work, is that you can define a "looked up color" (i.e. a color-valued variable) and apply it to a node in the scene graph. The value is inherited by any node descended from that node in the scene graph.
Now have a browse through the default style sheet, modena.css. The way this works is that almost everything is defined in terms of a very short list of looked-up colors. The consequence is that you can readily "theme" your applications just by redefining those colors on the root of the scene. Try adding this stylesheet to your favorite JavaFX application:
.root {
-fx-base: #c7dec7;
-fx-accent: #00c996 ;
-fx-default-button: #abedd8 ;
-fx-focus-color: #03d39e;
-fx-faint-focus-color: #03d39e22;
}
As you've observed, -fx-border is not used at all in the default stylesheet; instead borders are implemented by defining "nested" background colors which are essentially rectangular fills laid on top of each other. This is apparently more efficient (quite considerably so, by my understanding). So you are correct that making the inner of two backgrounds transparent will simply reveal the "outer" border color, not the color of the background.
How to achieve what you're looking for
The background of a pane defaults to the looked-up color -fx-background, which in turn defaults to a lighter version of -fx-base. So if you stick to changing the color of the pane containing the buttons by changing -fx-background or -fx-base, then you can make the button appear transparent by setting its background to
-fx-background-color: (some-border-color), -fx-background ;
The default borders for buttons contain three values; -fx-shadow-highlight, -fx-outer-border, and -fx-inner-border. You could override the values for these individually, or just redefine the background color as you need.
An approximation to what you want is in this example: you can mess with the exact values for the thickness of the border (from the second -fx-background-insets value) and the radius of the corners to get it as you need. If you want to get fancy with it, play with combinations of ladders and gradients.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class StyledButtonExample extends Application {
private int currentColorIndex = 0 ;
private final String[] baseColors = new String[] {"#8ec919", "#bfe7ff", "#e6e6fa",
"#ffcfaf", "#fff7f7", "#3f474f"};
private StackPane root ;
#Override
public void start(Stage primaryStage) {
root = new StackPane();
Button button = new Button("Change colors");
button.setOnAction(event -> changeColors());
root.getChildren().add(button);
Scene scene = new Scene(root,400,400);
scene.getStylesheets().add(getClass().getResource("transparent-button.css").toExternalForm());
root.setStyle("-fx-base: "+baseColors[0]+";");
primaryStage.setScene(scene);
primaryStage.show();
}
private void changeColors() {
currentColorIndex = (currentColorIndex + 1) % baseColors.length ;
root.setStyle("-fx-base: "+baseColors[currentColorIndex]+";");
}
public static void main(String[] args) {
launch(args);
}
}
transparent-button.css:
.button {
-fx-background-color: derive(-fx-base, 60%), -fx-background ;
-fx-background-insets: 0, 1px ;
-fx-background-radius: 4px, 0 ;
}
.button:hover {
-fx-background-color: #fff, derive(-fx-background, -5%) ;
}

Resources