Mnemonics - how to set color? - javafx

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).

Related

JavaFX Text-Area remove borders

I am using an JavaFX Alert with a text area on it.
The problem I have is that the text area does not use the full space of the Alert, as well as having white (borders).
My code:
TextArea area = new TextArea("");
area.setWrapText(true);
area.setEditable(false);
area.getStylesheets().add(getClass().getResource("/model/app.css").toExternalForm());
Alert alert = new Alert(AlertType.NONE);
alert.getDialogPane().setPrefWidth(750);
alert.getDialogPane().setPrefHeight(800);
alert.getDialogPane().setContent(area);
formatDialog(alert.getDialogPane());
alert.setTitle("Lizenz Info");
Window w = alert.getDialogPane().getScene().getWindow();
w.setOnCloseRequest(e -> {
alert.hide();
});
w.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent event) {
if (event.getCode() == KeyCode.ESCAPE) {
w.hide();
}
}
});
alert.setResizable(true);
alert.showAndWait();
My corresponding css sheet:
.text-area .content {
-fx-background-color: #4c4c4c;
}
.text-area {
-fx-text-fill: #ff8800;
-fx-font-size: 15.0px;
}
.text-area .scroll-pane {
-fx-background-color: #4c4c4c;
}
.text-area .scroll-pane .viewport {
-fx-background-color: #4c4c4c;
}
.text-area .scroll-pane .content {
-fx-background-color: #4c4c4c;
}
.viewport and .content on .scrollpane did not have any effect whatsoever.
I want the white borders either to be gone, or have the same color as the background, also to use the full space of the dialog. Can someone help?
As #jewelsea suggested, I think Alert is not the right choice here. Your desired layout can be acheived by using Dialog (as in below code).
Dialog<String> dialog = new Dialog<>();
dialog.setTitle("Lizenz Info");
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK);
dialog.getDialogPane().setContent(area);
dialog.setResizable(true);
dialog.showAndWait();
Having said that, you can fix the existing issues as below:
Remove white space around text area: You can remove the white space by setting the padding of TextArea to 0. Include the below code in the css file.
.text-area{
-fx-padding:0px;
}
Changing the white space background : The .text-area and .content styleclasses are on same node. So instead of declaring with space between them
.text-area .content {
-fx-background-color: #4c4c4c;
}
you have to declare without the space between the styleclasses (in below code)
.text-area.content {
-fx-background-color: #4c4c4c;
}
Here is a similar example to Sai's but uses a standard stage.
It uses a UTILITY style, but you could use a different style if you prefer.
Basically, if you don't want the additional styling and functionality of the alerts and dialogs (and you don't seem to with at least the example you have given), then you can just use a standard stage to display your content rather than the dialog classes provided in the javafx.control package.
The alert.css file referenced in the example is the CSS from your question.
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class TextAreaUtility extends Application {
public static void main(String[] args) {
Application.launch(args);
}
#Override
public void start(Stage stage) {
Button showAlert = new Button("Show Alert");
showAlert.setOnAction(this::showAlert);
stage.setScene(new Scene(showAlert));
stage.show();
}
private void showAlert(ActionEvent e) {
TextArea textArea = new TextArea("");
textArea.setWrapText(true);
textArea.setEditable(false);
Scene scene = new Scene(textArea, 750, 800);
scene.getStylesheets().add(
TextAreaUtility.class.getResource(
"alert.css"
).toExternalForm()
);
Stage utility = new Stage(StageStyle.UTILITY);
utility.initOwner(((Button) e.getSource()).getScene().getWindow());
utility.initModality(Modality.APPLICATION_MODAL);
utility.setTitle("Alert Title");
utility.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (event.getCode() == KeyCode.ESCAPE) {
utility.hide();
}
});
utility.setResizable(true);
utility.setScene(scene);
utility.showAndWait();
}
}
Debugging nodes and styles info
If you want to see the nodes and style names in your scene graph and you aren't using a tool like ScenicView, a quick debug function is:
private void logChildren(Node n, int lvl) {
for (int i = 0; i < lvl; i++) {
System.out.print(" ");
}
System.out.println(n + ", " + n.getLayoutBounds());
if (n instanceof Parent) {
for (Node c: ((Parent) n).getChildrenUnmodifiable()) {
logChildren(c, lvl+1);
}
}
}
Which you can attach to run when the window is displayed:
w.setOnShown(se -> logChildren(alert.getDialogPane().getScene().getRoot(), 0));
When you run this on a standard dialog you will see quite a few nodes in the scene graph with attached styles that you can find defined in the modena.css file within the JavaFX SDK. You will also see that some of the bounding boxes for the layout that are not related to your text area have width and height.
Those dialog styles by default have padding attached to them, which is why you are seeing padding around your TextArea. The padding is not in the text area but the content regions containing it within the dialog. To get rid of it, you need to set the padding in your custom CSS to override the default. I don't have the CSS for that, it is difficult to create sometimes and overriding default padding is probably best avoided when possible.

JavaFX .setStyle inline sub elements

In order to style the background for many elements in JavaFX, you need to use a css file, or to use .setStyle.
In my case I have to style the background of the dropdown from a ComboBox, but I have to use .setStyle not a css file (because I have some dynamic colors that will be used to style different GUI elements). The problem here is that if I use the following css code, the function .setStyle doesn't recognize it as if I were to use a css file.
.setStyle(".combo-box .list-cell{ -fx-background: blue;}");
The code would look like this:
comboBox.setStyle(".combo-box .list-cell{ -fx-background: #"+ Color1.toString().substring(2) + ";}");
Color1 beeing a Color object, that will get a dynamic value depending on the case.
The question is, can I use .list-cell inside the function .setStyle? If so, how? This would help me with other GUI elements were I'll have to use .setStyle.
It's possible to use a looked-up colors for this. You can assign those using setStyle and use them from a CSS stylesheet:
#Override
public void start(Stage primaryStage) {
ComboBox<String> comboBox = new ComboBox<>();
comboBox.getItems().addAll("A", "B", "C");
StackPane root = new StackPane(comboBox);
// set color
root.setStyle("cell-color: blue;");
Scene scene = new Scene(root, 400, 400);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
}
style.css
/* default values */
.root {
cell-color: yellow;
}
/* use color */
.combo-box .list-cell {
-fx-background: cell-color;
}
For what I have, I like this solution better.
comboBox.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
public ListCell<String> call(ListView<String> param) {
return new ListCell<String>() {
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
setText(item);
setBackground(new Background(new BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)));
setTextFill(Color.BLUE);
}
};
}
});

How to have a button focused when pressing 'Tab' button in javaFX?

This is the Image link of my fxml file...
In the above shown window of a simple form in javaFx when I press tab button it will go to ok button and next tab will shift to cancel button. However the focus as shown on the textfield is not transferred to the buttons.But when the mouse cursor is moved on them the hover effect works perfectly.
How to make these buttons focused/hovered with different colors when pressing the tab button (not by moving the mouse cursor on them)?
Thanks in anticipation.
You can set the colors for the buttons in a stylesheeet.
public class YourApp extends Application {
#Override
public void start(Stage primaryStage) {
TextField txt = new TextField("test");
Button btnOk = new Button("OK");
btnOk.setId("buttonOk");
Button btnCancel = new Button("Cancel");
btnCancel.setId("buttonCancel");
VBox box = new VBox(txt, btnOk, btnCancel);
Scene scene = new Scene(box);
scene.getStylesheets().add(getClass().getResource("yourApp.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
yourApp.css:
#buttonCancel:hover,
#buttonCancel:focused {
-fx-background-color: blue;
}
#buttonOk:hover,
#buttonOk:focused{
-fx-background-color: green;
}

How do you set JavaFX TabPane CSS in code?

https://stackoverflow.com/a/10615258/529411
I would like to add a background color to my tabpane dynamically (depending on certain conditions). How can I achieve this from code? One option is to assign he tab a specific ID which has the associated CSS, but in my case the color can be dynamically chosen by the user.
Also, I'm curious how to apply the styles in code when dealing with a hierarchy of components.
You can assign the background color to be a looked-up color in the CSS file:
.tab-pane > .tab-header-area > .tab-header-background {
-fx-background-color: -fx-outer-border, -fx-text-box-border, my-tab-header-background ;
}
Now in code you can set the value of the looked-up color whenever you need to:
tabPane.setStyle("my-tab-header-background: blue ;");
SSCCE:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.stage.Stage;
public class DynamicTabHeaderBackground extends Application {
private static final String TAB_HEADER_BACKGROUND_KEY = "my-tab-header-background" ;
#Override
public void start(Stage primaryStage) {
TabPane tabPane = new TabPane();
tabPane.setStyle(TAB_HEADER_BACKGROUND_KEY+": blue ;");
tabPane.getTabs().addAll(new Tab("Tab 1"), new Tab("Tab 2"));
tabPane.getSelectionModel().selectedIndexProperty().addListener((obs, oldIndex, newIndex) -> {
if (newIndex.intValue() == 0) {
tabPane.setStyle(TAB_HEADER_BACKGROUND_KEY+": blue ;");
} else {
tabPane.setStyle(TAB_HEADER_BACKGROUND_KEY+": green ;");
}
});
Scene scene = new Scene(tabPane, 400, 400);
scene.getStylesheets().add("dynamic-tab-header.css");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
with dynamic-tab-header.css containing the CSS code above.
Update
If you have multiple tab panes, you might want to consider the following variant of the CSS file:
.tab-pane {
my-tab-header-background: derive(-fx-text-box-border, 30%) ;
}
.tab-pane > .tab-header-area > .tab-header-background {
-fx-background-color: -fx-outer-border, -fx-text-box-border,
linear-gradient(from 0px 0px to 0px 5px, -fx-text-box-border, my-tab-header-background) ;
}
This basically emulates the default behavior, but allows you to modify the background on any particular tab pane by calling the tabPane.setStyle(...) code as before.

JavaFX disabled element styling

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.

Resources