I'm playing around with JavaFx and seem to have a problem getting the menu-bar to look exactly how I want using css.
The main menu bar seems to be okay. When I hover or select the background becomes darker and the font becomes blue ("Edit" in the example). The same with the menu-item below ("Delete" in the example) but it seems that the other non-hovered, non-selected menu-items also get blue text instead of remaining white.
I've tried looking at https://docs.oracle.com/javase/8/javafx/api/javafx/scene/doc-files/cssref.html and other StackOverflow articles, and just a bunch of trial and error, but nothing seems to do it. Any tips?
Source code is at https://github.com/pnogas/TornadoTest, but I'll have snippets below in case I ever delete it from github for future people reading this.
FXML generated from scene builder then auto-formatted from intelliJ IDE
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox prefHeight="400.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.paulnogas.log.analyzer.MainView">
<MenuBar stylesheets="@test.css" VBox.vgrow="NEVER">
<Menu mnemonicParsing="false" text="Edit">
<MenuItem mnemonicParsing="false" text="Undo"/>
<MenuItem mnemonicParsing="false" text="Redo"/>
<SeparatorMenuItem mnemonicParsing="false"/>
<MenuItem mnemonicParsing="false" text="Cut"/>
<MenuItem mnemonicParsing="false" text="Copy"/>
<MenuItem mnemonicParsing="false" text="Paste"/>
<MenuItem mnemonicParsing="false" text="Delete"/>
<SeparatorMenuItem mnemonicParsing="false"/>
<MenuItem mnemonicParsing="false" text="Select All"/>
<MenuItem mnemonicParsing="false" text="Unselect All"/>
</Menu>
and here's the relevant parts of test.css
.menu-bar,
.menu,
.menu-item {
-fx-background-color: #222222;
}
.menu-bar .label,
.menu .label,
.menu-item .label {
-fx-text-fill: white;
}
.menu:hover,
.menu:showing,
.menu-item:hover {
-fx-background-color: #111111;
}
.menu:hover .label,
.menu:showing .label,
.menu-item:hover .label {
-fx-text-fill: #80CBC4;
}
(I know TornadoFX prefers type-safe CSS in Kotlin to a normal *.css file, but I think I want to do it in *.css for now. I want to use Scene Builder occasionally. I also like the strict forcing of separation of concerns. When working in Kotlin only I tend to lose discipline and end up with spaghetti code mixing structure, style, functionality in one ugly Kotlin class. Maybe I'll move it over to pure Kotlin later).
The selector (as an example)
.menu:showing .label
will select all labels that are descendants of a showing menu. So this includes labels which are child nodes of a menu item which is a child node of a showing menu, etc. Here you want to only select labels which are immediate children of a showing menu. The correct selector syntax for that is
.menu:showing > .label
The CSS you need is
.menu-bar,
.menu,
.menu-item {
-fx-background-color: #222222;
}
.menu-bar > .label,
.menu > .label,
.menu-item > .label {
-fx-text-fill: white;
}
.menu:hover,
.menu:showing,
.menu-item:hover {
-fx-background-color: #111111;
}
.menu:hover > .label,
.menu:showing > .label,
.menu-item:hover > .label {
-fx-text-fill: #80CBC4;
}
Another solution would be to explicitly set the text color of labels in menu items in showing menus with and without the :hover
psuedoclass:
.menu-bar,
.menu,
.menu-item {
-fx-background-color: #222222;
}
/* Note added .menu:showing .menu-item .label selector */
.menu-bar .label,
.menu .label,
.menu-item .label,
.menu:showing .menu-item .label {
-fx-text-fill: white;
}
.menu:hover,
.menu:showing,
.menu-item:hover {
-fx-background-color: #111111;
}
.menu:hover .label,
.menu:showing .label,
.menu:showing .menu-item:hover .label {
-fx-text-fill: #80CBC4;
}