JavaFX disabled element styling - css

I have a combo box with some data.
public class Test extends Application {
public static final String[] items = "One Two Three".split(" ");
#Override
public void start(Stage primaryStage) throws Exception {
final ComboBox<String> box = new ComboBox<>(FXCollections.observableArrayList(items));
box.getSelectionModel().selectFirst();
primaryStage.setScene(new Scene(box));
primaryStage.show();
}
}
If I set combo box disabled it grayed but I need to set text black. Google says what I need to set opacity to 1.0.
box.setDisable(true);
box.setStyle("-fx-opacity: 1.0;");
And nothing happens. It also grayed.
Even if I set text-fill property to black it also grayed.
box.setDisable(true);
box.setStyle("-fx-opacity: 1.0; -fx-text-fill: black;");
What happens? How do I change text color of disabled combo box?

The disabled property cascades from a scene graph node to its child nodes, so all the child nodes of the combo box effectively pick up their :disabled CSS styles. So, for example, the Label displaying the selected item uses its disabled style, which has opacity set to 0.4.
To achieve what you want, do
.combo-box:disabled, .combo-box:disabled > * {
-fx-opacity: 1.0 ;
}
in an external CSS file.

Related

Mnemonics - how to set color?

I have multiple buttons in in my javafx appliaction with mnemonics.
When I press "Alt" the mnemonics appear in a dark color but I want them to be white.
What is the right css selector for this?
I tried:
.mnemonic-underline: {
-fx-stroke: white;
}
But after that the underlines are visible all the time.
This should work:
:show-mnemonics > .mnemonic-underline {
-fx-stroke: white;
}
Example program:
public class MnemonicStylingSSCCE extends Application {
#Override
public void start(Stage stage) {
// Init label
final Label mnemonic = new Label("_Mnemonic");
mnemonic.setMnemonicParsing(true);
// Init scene
final Scene scene = new Scene(mnemonic);
scene.getStylesheets().add(MnemonicStylingSSCCE.class.getResource("mnemonic.css").toExternalForm());
stage.setScene(scene);
// Request focus & show
stage.requestFocus();
stage.show();
}
}
Side note - the content of mnemonic.css is CSS shown above (but with the red color instead of white).

JavaFX primaryStage binding with TextField

In JavaFx I'm currently trying to change the height of
primaryStage via binding.
primaryStage.setScene(scene);
primaryStage.setHeight(400.0);
primaryStage.widthProperty().bindBidirectional(textField.textProperty());
It's just a homework problem, not meaningful.
Unfortunately primaryStage is readOnlyDoubleProperty. May I change this settings to gain write-permissions?
I know, there is the possibility to change the window size via EventHandler, but I would like to change the window size on the fly through the TextField with bindings.
So any newly entered number enlarges the window.
Any ideas?
It's definitely possible and I hope there is a better way and no one should ever use this code ever but this is what I managed to make work
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
TextField textField = new TextField();
//Allows for only numeric input
textField.setTextFormatter(new TextFormatter<>(change -> {
if (change.getText().matches("[0-9]*"))
return change;
else
return null;
}));
primaryStage.setScene(new Scene(textField));
primaryStage.setHeight(200.0);
//Allows Program to start without error
primaryStage.setMaxWidth(200);
//Binds min and max to ensure stage width change due to only 1 possible size
primaryStage.minWidthProperty().bind(primaryStage.maxWidthProperty());
//Bind textfield to width
textField.textProperty().bindBidirectional(primaryStage.maxWidthProperty(), new NumberStringConverter());
primaryStage.show();
}
}

JavaFX trouble with fade transitions

I'm currently developing an app. It's visual structure is the following:
Only one Stage.
Only one Scene which has an ApplicationContainer's (my own class which
is basically a StackPane with a BorderPane inside of it with a
MenuBar on top, and the current page in it's center).
Multiple ApplicationLayout's
The ApplicationLayout has a Header and a Footer (footer not implemented yet) and looks like this:
I've managed to implement fadeIn / fadeOut transitions between the pages by setting a StackPane as the BorderPane's center, adding the page to it, and on top of that, a white VBox. So before I make the page switch I work with FadeTransitions of this white VBox.
I had to do it this way because setOpacity() wouldn't change the textfields or button opacities for some reason.
Now I'm trying to do the exact same thing for the header. So I setted a StackPane to the top, and added to it the header and a on top of it a "header coverer" which supposedly should do the trick just as before (can't modify the opacity property of the title, arrow or description because of CSS overriding).
But this time it's not working, if I set the opacity of the header coverer to anything but 0, the stuff in the header doesn't show.
What I want to acomplish is to fadeOut / FadeIn the components of the header but not the orange HBox.
EDIT: Added a minimal example where this doesn't work for me
public class Main extends Application {
private Boolean buttonPressed = false;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
BorderPane appWindow = new BorderPane();
appWindow.setStyle("-fx-alignment: center; -fx-padding: 30 0 0 30");
appWindow.setBackground(new Background(new BackgroundFill(Color.PERU, null, null)));
GridPane loginContainer = new GridPane();
appWindow.setCenter(loginContainer);
TextField username = new TextField();
PasswordField password = new PasswordField();
Label userNameDesc = new Label("Username");
Label passwordDesc = new Label("Password");
Button logInBtn = new Button("Log In");
logInBtn.setTranslateX(100);
logInBtn.setTranslateY(20);
logInBtn.setOnAction(event -> {
if (!buttonPressed) {
appWindow.getCenter().setOpacity(30);
buttonPressed = true;
System.out.println("Opacity set to " + appWindow.getCenter().getOpacity());
}
else {
appWindow.getCenter().setOpacity(100);
buttonPressed = false;
System.out.println("Opacity set to " + appWindow.getCenter().getOpacity());
}
});
loginContainer.addColumn(0, userNameDesc, passwordDesc);
loginContainer.addColumn(1, username, password);
loginContainer.add(logInBtn, 1, 2);
Scene scene = new Scene(appWindow, 300, 250);
stage.setScene(scene);
stage.show();
}
}
Pressing the "Log In" button should affect the Gridpane and Gridpane childs visual opacity, but it doesn't. It just prints the correct opacity values.
According to the documentation:
Opacity is specified as a value between 0 and 1. Values less than 0 are treated as 0, values greater than 1 are treated as 1.
So setting the value to 30 or to 100 has no effect: both are treated as fully opaque (i.e. they are clamped at 1).
Replacing
appWindow.getCenter().setOpacity(30);
with
appWindow.getCenter().setOpacity(0.3);
will make the center content partially transparent.

JavaFX 8 - How to change the color of the prompt text of a NOT editable combobox via CSS?

The title says everything. I want to change the color of the prompt text of a not editable combobox, so that the text has the same color like the prompt text of a editable combobox.
In my CSS-file I tried to use -fx-prompt-text-fill in .combo-box, .combo-box-base, .combo-box-base .text-field and .combo-box-base .text-input, but nothing worked.
What styleclass do I have to use?
When the ComboBox is not editable, there is no TextField, and the property -fx-prompt-text-fill is no longer valid, since the control displayed instead, a ListCell, doesn't extend TextInputControl.
In order to set the style of this cell, we can provide our custom styled ListCell:
#Override
public void start(Stage primaryStage) {
ComboBox comboBox = new ComboBox();
comboBox.getItems().addAll("Item 1", "Item 2", "Item 3");
comboBox.setPromptText("Click to select");
comboBox.setEditable(false);
comboBox.setButtonCell(new ListCell(){
#Override
protected void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if(empty || item==null){
// styled like -fx-prompt-text-fill:
setStyle("-fx-text-fill: derive(-fx-control-inner-background,-30%)");
} else {
setStyle("-fx-text-fill: -fx-text-inner-color");
setText(item.toString());
}
}
});
Scene scene = new Scene(new StackPane(comboBox), 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
}
Hi I do beleive that I m providing a better solution
First
in your CSS file create the following
.input .text-field {
-fx-prompt-text-fill: #a0a0a0; // or any color you want
}
than in the scene builder set your combobox class to input after attaching the CSS file
That works like a sharm for me

Javafx ListView selection bar text color when using CellFactory

Is there any way to change the selection bar text color in a list view?
Preferably using CSS. In a TableView, you can use:
-fx-selection-bar-text: white;
But this does not work for a ListView.
UPDATE: The above case happens when using CellFactories to render the cells.
lvRooms.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override public ListCell<String> call(ListView<String> list) {
return new RoomCell();
}
});
In the Cell Factory class, I'd gladly cover the case when the row is selected.
But: It is called just once at the beginning, not every time the selection bar is moved, and therefore the isSelected() method always renders false.
UPDATE 2: This is the RoomCell implementation:
class RoomCell extends ListCell<String> {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
Log.debug("RoomCell called, item: "+item);
final Label lbl = new Label(item); // The room name will be displayed here
lbl.setFont(Font.font("Segoe UI", FontWeight.BOLD, 18));
lbl.setStyle("-fx-text-fill: black");
//lbl.setTextFill(isSelected()?Color.WHITE: Color.BLACK);
if (isSelected()) // This is always false :(
lbl.setStyle("-fx-text-fill: yellow");
if (Rooms.getBoolean(item, "OwnerStatus")) {
lbl.setEffect(new DropShadow(15, Color.BLUEVIOLET));
lbl.setGraphic(new ImageView(
new Image(getClass().getResourceAsStream("images/universal.png"))));
} else {
lbl.setGraphic(new ImageView(
new Image(getClass().getResourceAsStream("images/yin-yang.png"))));
lbl.setEffect(new DropShadow(15, Color.WHITE));
}
setGraphic(lbl);
}
}
}
-fx-selection-bar-text is a color palette (not css property) defined in a root default CSS selector, which is selector of the Scene. I don't know how are you using it but if you define it (globally since it is scene's selector) like:
.root{
-fx-selection-bar-text: red;
}
in your CSS file then all controls' css properties using -fx-selection-bar-text will be red. ListView will be affected as well (see commented out original usages below).
However if you want to customize the ListView's style only, override the default properties this way
(Note: only -fx-text-fill are overriden. Original values are commented out, where -fx-selection-bar-text is used):
/* When the list-cell is selected and focused */
.list-view:focused .list-cell:filled:focused:selected {
-fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
-fx-background-insets: 0, 1, 2;
-fx-background: -fx-accent;
/* -fx-text-fill: -fx-selection-bar-text; */
-fx-text-fill: red;
}
/* When the list-cell is selected and selected-hovered but not focused.
Applied when the multiple items are selected but not focused */
.list-view:focused .list-cell:filled:selected, .list-view:focused .list-cell:filled:selected:hover {
-fx-background: -fx-accent;
-fx-background-color: -fx-selection-bar;
/* -fx-text-fill: -fx-selection-bar-text; */
-fx-text-fill: green;
}
/* When the list-cell is selected, focused and mouse hovered */
.list-view:focused .list-cell:filled:focused:selected:hover {
-fx-background: -fx-accent;
-fx-background-color: -fx-focus-color, -fx-cell-focus-inner-border, -fx-selection-bar;
-fx-background-insets: 0, 1, 2;
/* -fx-text-fill: -fx-selection-bar-text; */
-fx-text-fill: yellow;
}
These CSS properties and more are avaliable in built-in caspian.css.
UPDATE: I strongly advice you to read the Cell API. From there
... We represent extremely large data sets using only very few Cells.
Each Cell is "recycled", or reused.
Be warned about the different String items may use the same cell, ending with misleading visual effects/renderings, like isSelected() in your code. Additionally in API it says
Because by far the most common use case for cells is to show text to a
user, this use case is specially optimized for within Cell. This is
done by Cell extending from Labeled. This means that subclasses of
Cell need only set the text property, rather than create a separate
Label and set that within the Cell.
So I refactored your code as follows.
class RoomCell extends ListCell<String> {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
Log.debug("RoomCell called, item: "+item);
setFont(Font.font("Segoe UI", FontWeight.BOLD, 18));
ImageView iView = new ImageView();
if (Rooms.getBoolean(item, "OwnerStatus")) {
iView.setEffect(new DropShadow(15, Color.BLUEVIOLET));
iView.setImage(new Image(getClass().getResourceAsStream("images/universal.png")));
} else {
iView.setEffect(new DropShadow(15, Color.WHITE));
iView.setImage(new Image(getClass().getResourceAsStream("images/yin-yang.png")));
}
setGraphic(iView); // The image will be displayed here
setText(item); // The room name will be displayed here
}
}
}
All -fx-text-fill styles of the cell's text will change according to definitions in CSS file.
Now here is a trade-off between cell's text dropshadow effect and its fill colors from CSS file:
-- if you want to use dropshadow effect, you should go like current way, namely creating label, setting its text, give dorpshadow effect to the label and setGraphic(label). However this time you will not prefer to set the text (setText(item)) of the cell thus text color styles in CSS file will have no effect.
-- On other hand, if you prefer the code that I have refactored, then you should to disable -fx-background-color of the cell (which extends Labeled) by setting it to transparent or null and set the -fx-effect to dropshadow in CSS file to be able to apply dropshadow effect to the text directly. Clearing the background of the cell is not the preferred way either IMO. An explanation by the code:
Label lbl = new Label("This text will have a dropshadow on itself directly");
lbl.setEffect(new DropShadow(15, Color.BLUE));
Label another_lbl = new Label("This text will have a dropshadow applied on the background bounds, not to text");
another_lbl.setEffect(new DropShadow(15, Color.BLUE));
another_lbl.setStyle("-fx-background-color:gray");
Test them to see the difference. That's all.

Resources