How to change styling for disabled ListView in JavaFX? - java

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;
}

Related

How do I change the color of an anchorpane from the controller class?

For a GUI I'm making the minimize, maximize, close buttons similar to that of Spotify by using an anchorpane for each 'button'. I created the buttons via scenebuilder and they are loaded to the class via fxml. I can't figure out how to call a particular instance of an anchorpane in the controller class to change its background color when the mouse enters or exits.
public static Stage primaryStage;
#Override
public void start(Stage primaryStage) throws Exception
{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setScene(new Scene(root, 1280, 800));
...
this.primaryStage = primaryStage;
etc.
is how the UI class is set up
I expect the color of the anchorpane to change when the mouse enters the bounds, but as of now I have no idea how to call it.
Solved it, had to set an fxid to the anchorpane and then initiate it in the controller class after an #FXML.
Kinda like this:
#FXML
Anchorpane someButton;
#FXML
public void makeButtonWhite(MouseEvent event)
{
someButton.setStyle("-fx-background-color: #ffffff");
}
The most convenient way of doing this imho is using a stylesheet to assign the background.
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" stylesheets="#style.css">
<children>
<AnchorPane prefWidth="30" prefHeight="20" styleClass="my-button"/>
</children>
</AnchorPane>
style.css (same directory as fxml)
/* default style */
.my-button {
-fx-background-color: blue;
}
/* style when mouse is inside the region */
.my-button:hover {
-fx-background-color: red;
}
This allows you to easily add the style to multiple Regions; you simply need to add the style class it (styleClass="my-button").
the code you need for starting this must be the starting class
public class Class extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
try {
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(this.getClass().getResource("/Folder/File.fxml"));
loader.setController(yourControllerClass());
//only if you do something with the controller class afterwards
YourControllerClass controller = loader.setController();
Parent parent = loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(parent);
primaryStage.setScene(scene);
primaryStage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
}
you know the code method in scenebuilder there you can set on mouse entered and exited for a button, a label etc. then if for example the button with the id "closeButton" and the OnMouseEntered "closeButtonOnEntered" and the OnMouseExited "closeButtonOnExited"
this will be the code you need
public yourcontrollerclass {
#FXML
Button closeButton;
#FXML
private void closeButtonOnEntered() {
//sets button red
button.setStyle("-fx-background-color: #ff0000");
}
#FXML
private void closeButtonOnExited() {
//sets button your first color
button.setStyle("-fx-background-color: transparent");
}
}
this can be done with nearly every thing in sceneBuilder
I hope i could help you(sorry for my bad english)

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.

JavaFX- how to hide tab content area and show only tab headers on selection of specific tab

I want to provide a way for users to hide/ unhide tab pane contents without adding additional buttons to UI. One way I thought was to provide a "dummy" tab in tabpane and on selecting it, all contents of tabpane will be hidden, except for headers. On selecting any other tab, contents will be made visible again. I have tried changing min/max/pref width of tabpane.
You can simply set the max height of the TabPane:
public class Main extends Application {
private static final int TABPANE_HEADER_HEIGHT = 29;
#Override
public void start(Stage primaryStage) throws Exception{
BorderPane root = new BorderPane();
// Add simple tabs
TabPane tp = new TabPane();
tp.getTabs().add(new Tab("Tab1", new Label(" Content of the first tab")));
tp.getTabs().add(new Tab("Tab2", new Label(" Content of the second tab")));
// Create the Tab which hides the content
Tab hideTab = new Tab("Hide", new Label(" Content of the third tab"));
tp.getTabs().add(hideTab);
hideTab.selectedProperty().addListener((obs, oldval, newval) ->
tp.setMaxHeight(((newval) ? TABPANE_HEADER_HEIGHT : -1)));
root.setTop(tp);
Scene scene = new Scene(root, 300, 275);
scene.getStylesheets().addAll(getClass().getResource("style.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Result:
Note
You can do the same using CSS by adding a new pseudo-class for .tab-pane called e.g. tabcontenthidden. In this pseudo class the max height of the TabPane is the height of the tabs.
style.css
.root { TAB_HEADER_HEIGHT: 29; }
.tab-pane:tabcontenthidden { -fx-max-height: TAB_HEADER_HEIGHT; }
.tab-pane {
-fx-max-height: -1;
-fx-background-color: orange;
}
In the Java code, you can create a PseudoClass like
PseudoClass TABPANE_CONTENT_HIDDEN = PseudoClass.getPseudoClass("tabcontenthidden");
and you can activate this pseudo-class with the pseudoClassStateChanged method:
tabPane.pseudoClassStateChanged(TABPANE_CONTENT_HIDDEN, true); // false to show
Note2
You can add Buttons to the tab area like in this answer (one button to hide and show) which maybe more ergonomic than an additional Tab.

JavaFX Change textcolor of disabled textfield in CSS

I have a texfield in a stage:
#FXML
private TextField tfAdUsername;
tfAdUsername.setPromptText(userName);
tfAdUsername.setDisable(true);
The textcolor is lightgray, i want to change it to black:
.text-field:readonly {
-fx-background-color: #E0E0E2;
-fx-border-color: #94BBDA;
-fx-text-fill: #000000;
}
.text-field:disabled {
-fx-background-color: #E0E0E2;
-fx-border-color: #94BBDA;
-fx-text-fill: #000000;
}
This doesn't change the textcolor. What is the correct CSS Property to use?
The reason why color turns grey on disabling is because of the opacity change. Just try adding the following css to your textfield.
-fx-opacity: 1.0;
Working example (using setStyle() )
public class KeyStroke extends Application {
#Override
public void start(Stage primaryStage) {
Pane root = new Pane();
TextField textField = new TextField("Itachi");
textField.setDisable(true);
textField.setStyle("-fx-opacity: 1.0;");
root.getChildren().add(textField);
Scene scene = new Scene(root, 200, 200);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
For changing the opacity use:
.text-input:disabled {
-fx-opacity: 1.0;
}
in the css file.
To change the textcolor used (after i read the question properly i know this wasn't asked.)
From the modena.css stylesheet:
.root {
/* Used for the inside of text boxes, password boxes, lists, trees, and
* tables. See also -fx-text-inner-color, which should be used as the
* -fx-text-fill value for text painted on top of backgrounds colored
* with -fx-control-inner-background.
*/
-fx-control-inner-background: derive(-fx-base,80%);
/* Version of -fx-control-inner-background for alternative rows */
-fx-control-inner-background-alt: derive(-fx-control-inner-background,-2%);
/* One of these colors will be chosen based upon a ladder calculation
* that uses the brightness of a background color. Instead of using these
* colors directly as -fx-text-fill values, the sections in this file should
* use a derived color to match the background in use. See also:
*
* -fx-text-base-color for text on top of -fx-base, -fx-color, and -fx-body-color
* -fx-text-background-color for text on top of -fx-background
* -fx-text-inner-color for text on top of -fx-control-inner-color
* -fx-selection-bar-text for text on top of -fx-selection-bar
*/
}
.root {
-fx-text-inner-color: #FF01F3;
}
For example:
#Override
public void start(Stage primaryStage) {
VBox root = new VBox();
root.setAlignment(Pos.CENTER);
Button btn = new Button();
TextField text= new TextField();
btn.setText("Press me!");
btn.setOnAction((ActionEvent event) -> {
text.setText("Goodbye World");
});
root.getChildren().addAll(btn, text);
Scene scene = new Scene(root, 300, 250);
scene.getStylesheets().addAll(getClass().getResource("css.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
And the color of the text in the textfield will be pink?purple?
This is by the way not a means to change the color for each textfield individually, if you change this for the root then all the textfields will use this color instead of the usual black. I don't know how to change the color for one textfield to blue and for another one in the same application to red.

CSS error in JavaFX project

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.

Categories