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
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.
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;
}
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);
}
// ...
}
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.
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