CSS error in JavaFX project - java

I'm trying to add a background image to my AnchorPane in JavaFX using a stylesheet called Style.css
When I run the program I get the following warning:
WARNING: com.sun.javafx.css.parser.CSSParser declaration CSS Error
parsing in-line style 'AnchorPane' from javafx.scene.Node$22#5c4a9e8e:
Expected COLON at [-1,-1]
My CSS file looks like this:
#AnchorPane{
-fx-background-image:url('penthouse.png');
-fx-background-repeat: no-repeat;
}
.chat{
-fx-background-image:url('penthouse.png');
-fx-background-repeat: no-repeat;
}
#btnSend{
}
#txtMessage{
}
#Figur{
-fx-background-image:url('Figur.png');
}
My Java code looks like this:
public void start(Stage primaryStage) throws Exception {
BorderPane bp = new BorderPane();
bp.setRight(createRightOptionPane());
bp.setBottom(createMessagePane());
bp.setCenter(createVisualChat());
Group root = new Group();
root.getChildren().add(bp);
Scene scene = new Scene(root);
// adding the stylesheet to the scene
scene.getStylesheets().add("Style.css");
primaryStage.setScene(scene);
primaryStage.setWidth(478);
primaryStage.setHeight(433);
primaryStage.setTitle("Chat");
primaryStage.show();
}
private Node createVisualChat() {
AnchorPane chat = new AnchorPane();
// setting the anchorPanes ID to AnchorPane
chat.setStyle("AnchorPane");
return chat;
}
Can anyone tell me what is wrong with this code?

In your code at line
// setting the anchorPanes ID to AnchorPane
chat.setStyle("AnchorPane");
you are setting the style not ID. It should be
chat.setId("AnchorPane");
See Skinning JavaFX Applications with CSS for more details.

Related

Make WebView ignore scene CSS in JavaFX

When I load a site / html using javafx.scene.web.WebView that site seems to be affected by my scene custom styling. A minimal example to demonstrate the issue.
Main.java
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
VBox root = new VBox();
primaryStage.setScene(new Scene(root, 900, 900));
String css = Main.class.getResource("/test.css").toExternalForm();
primaryStage.getScene().getStylesheets().add(css);
WebView webView = new WebView();
root.getChildren().add(webView);
webView.getEngine().load("http://google.pl");
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
test.css
.text-area,
.text-field {
-fx-background-color: red;
}
This results in
Ultimately I wish for a method like webview.getEngine().dontInheritStyles()of course there is none and I couldn't find any method of doing it otherwise. Tried:
webView.getStylesheets().clear();
webView.setStyle(null);
webView.getStyleClass().clear();
none of them worked. One way that I think could make this work (haven't tried it yet tho) would be to open the webview in a sub window which doesn't use the same scene, however I want the webview to be embeded in my existing application view so that option would be my last resort and I rather avoid it.
You can use some kind of hack, such as a combination of JavaFX and Swing.
You have two classes:
JFXPanel - which allows you to embed a JavaFX control into Swing
SwingNode - which allows you to embed a Swing control into JavaFX
You can combine the use of the JFXPanel and SwingNode classes in the wrapper class:
public class Styleless<T extends Parent> extends StackPane {
private T root;
public Styleless(T root) {
this.root = root;
JFXPanel jfxPanel = new JFXPanel();
jfxPanel.setScene(new Scene(root));
SwingNode swingNode = new SwingNode();
swingNode.setContent(jfxPanel);
getChildren().add(swingNode);
}
public T getRoot() {
return root;
}
}
And you can use it like this:
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
VBox root = new VBox();
primaryStage.setScene(new Scene(root, 900, 900));
String css = Main.class.getResource("/test.css").toExternalForm();
primaryStage.getScene().getStylesheets().add(css);
WebView webView = new WebView();
webView.getEngine().load("http://google.pl");
Styleless<WebView> webViewStyleless = new Styleless<>(webView);
root.getChildren().add(webViewStyleless);
VBox.setVgrow(webViewStyleless, Priority.ALWAYS);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
You can also use style classes in your CSS to manage which elements get styles applied to them. Define a 'myapplication' class in your css, and add that class to your root node.
test.css
/* any text fields inside a container with the myapplication style class */
.myapplication > .text-field{
-fx-background-color: red;
}
/* any text areas inside a container with the myapplication style class */
.myapplication > .text-area{
-fx-background-color: red;
}
Main.java
...
root.getStyleClass().add("myapplication");
TextField txtField = new TextField("Application text field");
root.getChildren().addAll(webView, txtField);
...
Using the '>' css selector (https://www.w3schools.com/cssref/css_selectors.asp) this way will apply the style to text fields whose parent has the style class 'myapplication'. When a WebView is created, it has the style class 'web-view' (https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html#webview)
While there is no real way to prevent style values from being inherited, style classes are not added to children.

How to change styling for disabled ListView in JavaFX?

I'm trying to make a disabled ListView look the same as a non-disabled ListView.
I looked it up and found that you have to set the opacity to 1 and have tried a number of approaches, with and without stylesheets, but none seem to work. I have tried:
listView.setStyle("-fx-opacity: 1.0;");
.listView:disabled {
-fx-opacity: 1.0;
}
.listView .list-cell {
-fx-opacity: 1.0;
}
.listView .list-cell:disabled {
-fx-opacity : 1.0;
}
I have also tried setting the background-color to white but this makes the text invisble for some reason, even though no other color does that. How would I go about doing this? Thanks.
Setting the opacity in the disabled pseudo-class (as you mentioned) should be enough:
.list-view:disabled {
-fx-opacity: 1;
}
just dont forget to add the stylesheet to the Scene:
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
As an example:
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
ListView<String> lw = new ListView<>();
lw.setItems(FXCollections.observableArrayList("dog", "cat", "whale"));
lw.setDisable(true);
root.setCenter(lw);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
and the CSS selector is contained in the file application.css and this file placed in the same directory as the Application class file.
Note: If you would like to have the selection also to look like the same, you can define the following selectors also:
.list-cell:disabled,
.list-cell:disabled,
.list-view:disabled {
-fx-opacity: 1;
}

JavaFX Same textarea with different Pane's

I have a project with maven, javafx and fxml. I have one main BorderPane, welcome.fxml, and Pane, ready.fxml.
My start method is;
#Override
public void start(Stage primaryStage) throws Exception {
try {
Pane root = (Pane) FXMLLoader.load(getClass().getResource("welcome.fxml"));
Scene scene = new Scene(root, 640, 480);
primaryStage.setScene(scene);
primaryStage.show();
} catch (Exception e) {
makeAlert(e, false);
}
}
Now, I have a button in my welcome.fxml, and I want to change my BorderPane's center with ready.fxml. Here is my button handler;
#FXML
private void buttonHandler() throws IOException, InterruptedException {
stage = (Stage) myButton.getScene().getWindow();
Pane sub = (Pane) FXMLLoader.load(getClass().getResource("../ready.fxml"));
BorderPane root = (BorderPane) FXMLLoader.load(getClass().getResource("../welcome.fxml"));
root.setCenter(sub);
//Scene scene = new Scene(root, 640, 480);
//stage.getScene().setRoot(root);
}
UPDATE: Here is my mistake,as #James_D noticed, I load welcome.fxml again in my controller and so, my whole Scene changes insted of only center.
The correct way should be;
stage = (Stage) brokerConnect.getScene().getWindow();
Pane center = (Pane) FXMLLoader.load(getClass().getResource("../ready.fxml"));
// FIXME: Get root like this
BorderPane root = (BorderPane) stage.getScene().getRoot();
root.setCenter(center);
EDITED: Java codes added.
You should update the center of the existing border pane, not create a new one and set the center of the new one.
All you need is to inject the border pane into the controller in the usual way. So add a fx:id to the root element of welcome.fxml:
<!-- imports, etc... -->
<BorderPane fx:id="root" fx:controller="..." xmlns:fx="..." ... >
<!-- ... -->
</BorderPane>
And then in the controller
public class Controller { /* or whatever name you have, again, you can't be bothered to post a MCVE */
#FXML
private BorderPane root ;
#FXML
private void buttonHandler() throws IOException {
Pane sub = (Pane) FXMLLoader.load(getClass().getResource("../ready.fxml"));
root.setCenter(sub);
}
// ...
}

JavaFX Anchor Constraints

I have an FXML file which has a split pane and 2 rectangles in it. I have both rectangles anchored properly via the FXML but from the code I am generating new rectangles but I can't seem to get the constraints on them working, I set them to the same settings as the rectangles in the FXML(constraint wise) but nothing. I think the issue is the rectangles in the FXML are inside a Split Pane where as the ones generated from the Java code are in the Main AnchorPane. Here is the code any ideas?
public void start(Stage stage) throws Exception {
//GridPane root = new GridPane();
AnchorPane root = fxmlLoader.load(getClass().getClassLoader().getResource("fxml/TestConveyorView.fxml")).getRoot();
Box box = new Box(1);
Rectangle rect = new Rectangle(50,50, box.getStatus().getColor());
rect.setX(385.0);
AnchorPane.setLeftAnchor(rect, 385.0);
AnchorPane.setRightAnchor(rect, 294.0);
root.getChildren().addAll(rect);
Scene scene = new Scene(root);
// BackgroundImage background = new BackgroundImage(null, BackgroundRepeat.REPEAT, BackgroundRepeat.REPEAT, BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT);
stage.setScene(scene);
stage.show();
}
Fixed by removing all the extra code in the main class like below.
public void start(Stage stage) throws Exception {
AnchorPane root = fxmlLoader.load(getClass().getClassLoader().getResource("fxml/TestConveyorView.fxml")).getRoot();
Scene scene = new Scene(root);
// BackgroundImage background = new BackgroundImage(null, BackgroundRepeat.REPEAT, BackgroundRepeat.REPEAT, BackgroundPosition.DEFAULT, BackgroundSize.DEFAULT);
stage.setScene(scene);
stage.show();
}
And adding these to things to my controller
#FXML
AnchorPane Splitright;
Splitright.getChildren().add(rectangle);
As it turns out the shapes were just being thrown on top of everything not actually being placed in the proper AnchorPane, which is what I suspected was happening.

Best reference for JavaFX CSS properties & selectors

I'm trying to learn JavaFX 2, but I've been stumbling a lot trying to style my application. I've found this document which tries to document controls and the css properties that apply to them. I can't tell if it's incomplete, if I should be using some unknown selectors or JavaFX's CSS support just isn't powerful enough for my needs.
Here are a couple of examples:
How would I change the background color for the area behind a TabPane without coloring every other child component (is there a selector for that, or perhaps a property?)
How would I change the color of non-selected tabs?
Have you tried something like this?
This uses an ID selector as shown in the "Skinning JavaFX Applications with CSS" document. You could also leave off the "#MyTabPane" selector and have it apply to all TabPane's. (It looks like the .tab and .tab-content-area selectors are not discussed in the reference guide. I went to the "caspian.css" file contained in jfxrt.jar file to find them.)
TabExample.css
#MyTabPane .tab {
-fx-background-color: blue;
}
#MyTabPane .tab:selected {
-fx-background-color: red;
}
#MyTabPane .tab-content-area {
-fx-background-color: cyan;
}
#MyTabPane .tab *.tab-label {
-fx-text-fill: white;
}
TabPaneEx.java
#Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Hello World");
StackPane root = new StackPane();
TabPane pane = new TabPane();
pane.setId(("MyTabPane"));
Tab tab1 = new Tab("ONE");
Tab tab2 = new Tab("TWO");
Tab tab3 = new Tab("THREE");
pane.getTabs().addAll(tab1,tab2,tab3);
Scene scene = new Scene(root, 300, 250);
root.getChildren().add(pane);
scene.getStylesheets().add(
this.getClass().getClassLoader().getResource("tabpaneex/TabExample.css").toString());
primaryStage.setScene(scene);
primaryStage.show();
}
JavaFX CSS Reference Guide
Skinning JavaFX Applications with CSS

Categories