JavaFX inline CSS hover effect - java

I am building a costume button by extending from a Label.
I know that you can use CSS within .java files with:
setStyle("-fx-background-color: #101010");
which is pretty cool and I am using this quite often.
But there is my problem: It seems like this doesn't work for hover effects.
In an external CSS file you can have:
#LabelButton:hover {
-fx-background-color: #aaaaaa;
}
I would like to have this feature with "XXX:hover" inside my Java File because the hex color code must be variable and this isn't possible when using external CSS files. So what I kinda want to have it this:
setStyle("hover:-fx-background-color: #101010");
But I can't find the right syntax for it let alone there is a syntax.
If there is no such feature, how should I do it then?
Thanks!

There is no way to use selectors of any kind in inline CSS. The inline style is always applied to the node regardless of it's state (with the exception of you assigning the corresponding node property).
You could bind the style property to the hover property of the node.
myButton.styleProperty().bind(Bindings.when(myButton.hoverProperty())
.then("-fx-background-color: #101010")
.otherwise("-fx-background-color: #aaaaaa"));
This could become very ugly if you e.g. want to style focused buttons and pressed buttons differently. For this reason I recommend combining CSS and inline CSS to achieve the desired style:
You can define your own variables color variables in CSS:
stylesheet
.label-button { /* using style class for selector (ids are for single nodes) */
/* assign default values */
-fx-normal-background: yellow;
-fx-hovered-background: red;
-fx-background-color: -fx-normal-background;
}
.label-button:hover {
-fx-background-color: -fx-hovered-background;
}
java code
myButton.setStyle("-fx-normal-background: #101010; -fx-hovered-background: #aaaaaa;");

Related

JavaFX ControlsFx adding custom CSS (Notification)

I am using the controlsfx library, particularly it's Notifications component, however it's default CSS styling doesn't fit my applications style at all, so I'm trying to change it.
I tried using the solution provided in this post
Is there a way to change the built-in controlfx notification popup color?
So:
String css = this.getClass().getResource("notificationpopup.css").toExternalForm();
primaryStage.getScene().getStylesheets().add(css);
Notifications.create().owner(primaryStage).(...).show();
The CSS file is being successfully loaded, there are also no errors with adding it to the styleSheets, the style of the notification remains, however, the same. I have tried loading both a whole file identical, except my changes, to the one used in the library and short css file only with what I wanted to change
My css file changes, for reference:
.notification-pane .notification-bar > .pane {
-fx-background-color: linear-gradient(to top, #3e5151, #decba4);
-fx-padding: 0 7 0 7;
}
(for now I'm just trying to change the background to a gradient of my choice)
I have also, without success tried to implement advice from questions related to other controlsfx elements, that is to add the url to styleSheeT AFTER invoking show.
(I have also tried, just to check things out, brute changing the css inside the library jar, but somehow that also failed to work, as in the css remained the same, without any errors, even though I have modified the jar and added it again).
Since the explanation provided was very scarce, I am at a loss, as to what is wrong here.
Also in my solution I have to avoid invoking .owner() and assigning the notification to a particular stage, since then it shows up inside that stage, not on the screen outside it. Maybe that can be fixed by adding the stylesheet to some other element, not primaryStage? But for now I can't achieve any css change even when confining the notification to a stage
Kinda late to answer this. But if someone having this issue, you can fix it using those two methods.
Method 01
The issue might happen because you are using multiple stylesheets for your scene. Add your notificationpopup.css css to the begining of the arraylist. I dont have hard proofs how that fix the issue. But I think that happens because of the ordering of the stylesheets. (The overriding stylesheet should be placed after the original stylesheet inside the stylesheets arraylist. There cannot be other stylesheet(s) in between them.)
String css = this.getClass().getResource("notificationpopup.css").toExternalForm();
primaryStage.getScene().getStylesheets().add(0, css);
Method 02
Put !important to css class attributes. For ex:
.notification-bar > .pane {
-fx-background-color: red !important;
-fx-padding: 10 10 10 10 !important;
}
Two possible solutions to change the css styling for a component
In your controller class, invoke the getStyle() method as such
node.getStyle("-fx-background-color: linear-gradient(to top, #3e5151, #decba4);-fx-padding: 0 7 0 7;");
with the same code you would have in your css file on that node to style it directly and override the css values.
or
Give the node a unique CSS ID in your code or fxml file by saying
node.setId("myID");
and then in your css file writing whatever you need for that tag like
#myID {
-fx-background-color: red;
}

Javafx reset button css to previous style

Note: Javafx newbie
Problem:
Many websites and tutorial show one how to set the style of a button using classes or ID's.
After setting the style from an Id, I need to restore the style to the previous state or simply the .button class.
Some Styles:
I have the following css (extract) used for all my buttons:
.button {
-fx-text-fill: white;
-fx-font-family: "Arial Narrow";
-fx-font-weight: bold;
-fx-background-color: linear-gradient(#61a2b1, #2A5058);
-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );
}
and an Id for a button that is selected:
#button-selected {
-fx-background-color: linear-gradient(#3f6770, #82c0ce);
}
The code (extract):
//load stylesheet from resources into scene someScene.getStylesheets().add(Main.class.getResource("/gui.css").toExternalForm());
//...
Button b = new Button("some button");
//...
b.getStyleClass().add("button"); <----- adds .button class style to button
some trigger later on calls:
(activeButton, bSelectedButton) -> {
//...
if (!activeButton.equals(bSelectedButton)){
//restore activeButton to ".button" class
bSelectedButton.setId("button-selected");
}
//...
}
As a short summary above: (to put question into a practical application)
A trigger occurs, e.g. mouse click event, calling the lambda.
This checks if the buttons are the "same buttons", if not then:
clear the previous button's formatting activeButton,
and set the new button's bSelectedButton style with the #button-selected id.
Please note:
I have tried:
.button:pressed {
-fx-background-color: linear-gradient(#3f6770, #82c0ce);
}
but it does not change the colours as expected after the click (on the button)
Question:
How do I "unsetId" / "removeId" to restore the previous style of the button,
or simply how do I set the active style on the button from a loaded style sheet?
Use a toggle button rather than a standard button
You seem to be re-inventing the wheel. A selectable button is a ToggleButton, you should probably be using that. A toggle button has a selected psuedo-state that is used to configure the styling when the button is selected.
Aside comment on -fx-background-color usage
As an aside it is usually not best to directly set -fx-background-color for controls, but instead to set one of the higher level looked up colors, such as -fx-base. See modena.css for the definitions of these looked up colors and examples of how to use them (as well as the pseudo-state selectors).
Aside comment on -fx-effect usage
Setting a drop shadow effect on things can often lead to blurred text. For this reasons (and others), the standard way to simulate a shadow 3D effect for JavaFX controls is layered backgrounds, which is a bit complicated, but documented somewhat sparsely in the JavaFX CSS reference and abundant samples are in the modena.css file.
Advice on css id usage
The css id of an element should not change. It is used to identify the element, and should be unique in a given document. So you should not set and unset the id to something like button-selected. Instead you should use classes or pseudo-classes for maintaining keys to dynamic styling information.
You could effectively "unset" a CSS id by setting it to null, but I wouldn't advise that.
Related toggle button styling
Related answer mentions styling for ToggleButtons (but slightly different from the kind of styling you are asking for):
JavaFX - create custom button with image
Style by custom psuedo-class
If you really need to create your own psuedo-class, then see:
Example of using new Pseudoclass API in JavaFX 8 by james-d.
GuiGarage post on psuedo-classes
Style by style class setting
If you don't need or want to use pseudo-classes, then you can set different style classes on your control and use "and" style selectors:
styleclass.anotherstyleclass {
\\ your style attributes
}
For instance:
.button.selected {
-fx-base: palegreen;
}
With this method you would need to add and remove the additional style classes from the node's style class list as needed.
Generic selectable node styling
If you want a very generic selectable node style which is not tied to a button type, then see the solution here:
https://stackoverflow.com/a/40939611/1155209
In order to switch style by css file, you can use these commands:
scene.getStylesheets().clear();
setUserAgentStylesheet(null);
scene.getStylesheets().add(getClass().getResource("theme1.css").toExternalForm());
For your purpose, restoring previous style, I think you cannot do directly, but you can do as follows:
1) Use variable to store previousStyle.
2) When you switch to new style, you have to set value previousStyle is current style.
So, if you want to restore to previous style, you just call the previousStyle.
My solution does obey all css rules.
According to w3schools :
one should use an the id selector (denoted by #your_id_name) when referring to a specific/unique object.
The id of an element should be unique within a page, so the id selector is used to select one unique element!
NOTE: This rule is not adhered to in my solution
Solution:
CSS contains:
#button-default {
-fx-text-fill: white;
-fx-font-family: "Arial Narrow";
-fx-font-weight: bold;
-fx-background-color: linear-gradient(#61a2b1, #2A5058);
-fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );
}
#button-default:hover {
-fx-background-color: linear-gradient(#82c0ce, #3f6770);
}
#button-selected {
-fx-background-color: linear-gradient(#3f6770, #82c0ce);
}
Code:
When creating my buttons, I set the id there:
Button b = new Button();
//....
b.setId("button-default");
and some trigger event:
//....
(activeButton, newSelectedButton) -> {
if (!activeButton.equals(newSelectedButton)){
activeButton.setId("button-default");
newSelectedButton.setId("button-selected");
}
}
//....
A short summary:
The button is created with a specific id from the css file.
When some event gets triggered requiring the style change:
The button to be reset to the default style with an id referred to as button-default
Followed by setting the new buttons style with style referred to as button-selected
Note again: Not recommended since it does not adhere to standard practices, but I posted it here for completeness sake.

How to modify the ChoiceBox checkmark in JavaFX?

First of all, is it even possible to modify the ChoiceBox checkmark shape? Completely altering the CheckBox mark was easy enough using the CSS class (.check-box:selected .mark). However, all that I've found online for the ChoiceBox's ContextMenu's mark is that you can modify its color using -fx-mark-color within the .context-menu CSS class. I've tried several classnames to change the shape to a custom SVG to no avail.
.context-menu .menu-item:selected .mark {
-fx-shape: "M1,1 h4 v4 h-4 v-4 Z";
}
In the following picture I've completely reskinned my JavaFX application to match Mac's native Cocoa GUI, but the menu checkmark is the only flaw that appears to be impossible to fix.
Search the modena.css stylesheet for -fx-shape. For Java 8, You will find:
.check-menu-item:checked > .left-container > .check
This is the CSS selector for checkmarks inside menu items (it also covers checks for selected items in a ChoiceBox). Define the same CSS selection path in a custom CSS stylesheet. Inside that selector, place a -fx-shape rule that defines a custom svg path for the shape you wish to use for checks.

JavaFX 2.2 built-in controls have no default style

While the CSS styling tutorials mention both default style sheet (caspian.css) and default classes for built-in controls (like .line for Line), my controls seem to lack both (checked by debugger).
As a result, the do not react for additional custom CSS if I do not set their class explicitly, which is annoying and destroys the whole point of global CSS styling.
I would be grateful for any ideas of what may cause such behaviour.
In JavaFX, three CSS selectors are supported, which are analogous to Type Selectors, Class selectors, and ID selectors in standard CSS. It's important to be a bit careful with the word "class", which has different meanings in the Java world and the CSS world: a Java class is a CSS Type; a CSS class is set on a node via a property called styleClass.
The Type Selector is determined by the result of calling the method getTypeSelector, which is declared in the interface Styleable. Node implements this interface, and implements getTypeSelector to return
getClass().getName() without the package name
So any Node may be styled by specifying its simple class name:
Label {
-fx-text-fill: green ;
}
Line {
-fx-stroke: red ;
}
etc.
CSS classes are determined by the getStyleClass() method in Styleable, which returns a list of strings. (Note that nodes may have multiple style classes, though I have never understood why this is a List rather than a Set.) By default, this list is empty, but Control subclasses set this value via their default skin to be the "css-ized" version of the class name (Button becomes button, ComboBox becomes combo-box, etc.). Thus
.label {
-fx-text-fill: green ;
}
works, but
.line {
-fx-stroke: red ;
}
does not work without previously setting the style class:
Line line = new Line();
line.getStyleClass().add("line");
Finally, ID Selectors work by specifying an id on the node. Ids are intended to be unique among all nodes in the scene graph. So you can do
Line line = new Line();
line.setId("my-line");
with
#my-line {
-fx-stroke: red ;
}
So in your example, the style class is not set by default (Line is not a Control subclass). You must either set it "by hand", or use a type selector.
One last note: you mentioned that your line "lacked caspian.css". I'm not quite sure what that means (as Lines are not styled at all by the default stylesheet), but the default stylesheet is only loaded the first time a Control is instantiated. This is intended as a performance enhancement for scene graphs that use no controls (and so would not benefit from the default stylesheet anyway).

Change the style of a GWT CellTable dynamically, to visually mark it as disabled

I'm looking for a way to dynamically change the style of a GWT CellTable at runtime. I want to make the table look "disabled" by graying the color scheme, to match up with other input fields that are disabled. Right now, I can prevent people from using the table, but they don't get any visual hint.
I have a resource bundle to set the style of the table, like described here and here:
public interface DataTableStyle extends CellTable.Resources {
#Override
#Source({ CellTable.Style.DEFAULT_CSS, "DataTable.css" })
CellTable.Style cellTableStyle();
}
That's passed into the constructor, and has been working fine for a while now:
public DataTable(int pageSize) {
super(pageSize, getStyle());
}
protected static DataTableStyle getStyle() {
return GWT.create(DataTableStyle.class);
}
What I can't figure out is how to dynamically adjust the style of the table at runtime. I'm not sure whether it's not possible, or whether I'm just missing something.
I'm pretty sure that I can't change the style resources attached to the cell table once they're set. Since I can't do that, it seems like I should be able to use either addStyleDependentName() or addStyleName() in combination with additional CSS styles, but I can't figure out the right combination of changes.
To test, I tried to override my existing definition of .cellTableHeader. I know that I'm targeting the right style, because if I change background: #000000 to background: magenta in the original style, it works.
.cellTableHeader {
background: #000000;
color: #ffffff;
text-shadow: none;
}
One example I worked off of is here. That page suggests using CSS like this:
.cellTableHeader.cellTable-disabled {
background: magenta; /* just to make it obvious */
}
Then, in my code:
userTable.addStyleDependentName("disabled")
By itself, the .cellTableHeader.cellTable-disabled style results in a runtime error:
The following unobfuscated classes were present in a strict CssResource:
cellTable-disabled
Fix by adding String accessor method(s) to the CssResource interface for obfuscated classes, or using an #external declaration for unobfuscated classes.
The recommended workarounds are either to use #external on the style or annotate #NotStrict on the resource bundle. Both of those get me past the runtime error, but the style doesn't take effect. I've also tried various other things:
.cellTableHeader.disabled {
background: magenta; /* just to make it obvious */
}
or
.cellTableHeader .disabled {
background: magenta; /* just to make it obvious */
}
or
.cellTableHeader disabled {
background: magenta; /* just to make it obvious */
}
but at this point I'm really just grasping at straws.
There is no way to change the style resource directly at runtime.
I see two solutions:
Custom CellTableBuilder
With this solution the Style used by the CellTableBuilder is replaced at runtime, when the table is re-drawn the new style will be applied. This solution has an issue, the CellTable don't use the CellTableBuilder to set selection styles, therefore replacing style on the builder has no effect on the selection style.
Here a demo of the custom CellTableBuilder solution with the source code.
Style Proxy
A different solution is to proxy the Style used by the CellTable and the builder. At runtime you can change the effective Style used by the proxy. Because the DefaultCellTableBuilder stores the style values at construction time you need to create a custom one that don't cache it. I've found no issues, but I've not deeply tested it
Here a demo of the style proxy solution with the source code.

Categories

Resources