Different behavior of Text and Labeled controls in combination with css - css

I am working on a Javafx application and I tried to add some Labels, Buttons and Texts, which resizes when the user resizing the Scene. All Nodes are inside a VBox, which itself is inside a StackPane.
My test application:
public class Test extends Application
{
public static void main(String[] args)
{
launch(args);
}
#Override
public void start(final Stage primaryStage)
{
StackPane pane = new StackPane();
VBox box = new VBox();
box.setAlignment(Pos.CENTER);
Label l = new Label("Label");
Text t = new Text("Text");
t.getStyleClass().add("test");
Button b = new Button("Button");
pane.heightProperty().addListener(listener ->
{
double h = pane.getHeight()/5;
l.setFont(Font.font(l.getFont().getFamily(), h));
t.setFont(Font.font(t.getFont().getFamily(), h));
b.setFont(Font.font(b.getFont().getFamily(), h));
});
box.getChildren().addAll(l, t, b);
pane.getChildren().add(box);
primaryStage.setScene(new Scene(pane));
primaryStage.getScene().getStylesheets().add(Path.of("test.css").toUri().toString());
primaryStage.show();
}
}
If I resize the Stage it works as expected. But unfortunately only with pure Java code.
Because after adding my css file, the Labeled controls behave different. While the Text elements continue to change in size, the Labels and Buttons does not change their size anymore.
My css file, which does not work:
.label
{
-fx-text-fill: red;
-fx-font-family: impact;
}
.test
{
-fx-fill: red;
-fx-font-family: impact;
-fx-font-size: 2em;
}
.button
{
-fx-text-fill: red;
-fx-font-size: 2em;
}
I asked myself what I did wrong and have tested different css states. I found out, when I omit font values in css it works, otherwise it does not. Therewhile it does not matter which font value occurs, only one font value is required to miss the behavior.
My css file, which works:
.label
{
-fx-text-fill: red;
//-fx-font-family: impact;
}
.test
{
-fx-fill: red;
-fx-font-family: impact;
-fx-font-size: 2em;
}
.button
{
-fx-text-fill: red;
//-fx-font-size: 2em;
}
1. Question: -has changed, see below-
Do I missunderstand something about css and Javafx, or did I something wrong in my css file or is there a bug?
2. Question: -solved-
Have I to put the font values with java code or is there an other way to add the font?
Thank You for helping!
Update
As recommended I have studying the follow guide:
https://openjfx.io/javadoc/14/javafx.graphics/javafx/scene/doc-files/cssref.html
The JavaFX CSS implementation applies the following order of precedence:
The implementation allows designers to style an application by using style sheets to override property values set from code. For example, a call to rectangle.setFill(Color.YELLOW) can be overridden by an inline‑style or a style from an author stylesheet. This has implications for the cascade; particularly, when does a style from a style sheet override a value set from code? The JavaFX CSS implementation applies the following order of precedence: a style from a user agent style sheet has lower priority than a value set from code, which has lower priority than a Scene or Parent style sheet. Inline styles have highest precedence. Style sheets from a Parent instance are considered to be more specific than those styles from Scene style sheets.
In my case this means, I will use the inline style to make it proper.
thus the 2. Question is solved
But, because of Parent style sheet > value set from code, it also means, all Nodes are not allowed to change theire size, even the Text Node.
Therefore I changed my 1. Question to:
Why does the JavaFX CSS order of precedence differ between Text and Controls

Question 1:
It's not a bug, it's a conflict of priorities. .setFont() has a lower priority than that CSS. Just replace .setFont() to .setStyle() and sample will work as you planned:
l.setStyle("-fx-font-size:" + h + ";");
t.setStyle("-fx-font-size:" + h + ";");
b.setStyle("-fx-font-size:" + h + ";");
Question 2:
Try to keep all about styles in CSS. It's the best practice.

Related

JavaFX - Set different hover colors on toggle button based on toggle state

I have a toggle button in my program that starts/stops a script. I would like for this button to be green and say "START" when the button is not selected, and red and say "STOP" when it is selected. More importantly, I would like the unselected hover color to be a slightly darker version of the original green, and the selected hover color to be a slightly darker version of the red color. My current CSS for this button looks like this:
#startStopButton {
-fx-border-color:#d4d4d4;
-fx-background-color:#85eca5;
-fx-background-image: url("startButton.png");
-fx-background-size: 50px;
-fx-background-repeat: no-repeat;
-fx-background-position: 80% 50%;
-fx-alignment: CENTER_LEFT;
-fx-effect: dropshadow(three-pass-box, #e7e7e7, 15, 0, 0, 0);
}
#startStopButton:hover {
-fx-background-color:#80dc9c;
}
#startStopButton:selected{
-fx-background-color: #ff6060;
-fx-text:"STOP";
}
#startStopButton:selected:focused{
-fx-background-color: #ff6060;
-fx-text:"STOP";
}
Currently, this will work fine, except for when the button turns red. In this case, there is no hover effect. Within my FXML controller, there is a function that is activated every time this button is clicked:
private void startStopClick()
{
if(startStopButton.isSelected())
{
startStopButton.setText(" STOP");
// startStopButton.setStyle()
}
else {
startStopButton.setText(" START");
}
}
Is there any way to 1) set the button text within CSS so that I can leave that out of my controller?
2) Get the current toggle button state in CSS, so that I can have multiple hover effects. For example, something like this:
#startStopButton:unselected{
-fx-background-color: #ff6060;
-fx-text:"STOP";
}
If there is no way to do this in CSS, can I set the hover styles in the Java code in the FXML controller?
CSS properties are only available for the look of nodes. With a few exceptions the basic JavaFX nodes don't allow you to specify content via CSS. The text property of buttons is no exception; it cannot be set using CSS.
As for the colors: The rules occuring last override values assigned by rules with the same precedence occuring before them. This means the background color assigned by the rules for #startStopButton:selected and #startStopButton:selected:focused always override the color #startStopButton:hover assigns.
Since in both cases you want a darker color when hovering, the derive function and a lookedup color may work for you.
Example
#Override
public void start(Stage primaryStage) {
ToggleButton btn = new ToggleButton();
btn.getStyleClass().add("start-stop");
btn.textProperty().bind(Bindings.when(btn.selectedProperty()).then(" STOP").otherwise(" START"));
Pane p = new Pane(btn);
Scene scene = new Scene(p);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
style.css
.start-stop.toggle-button {
base-color: #85eca5;
-fx-background-color: base-color;
}
.start-stop.toggle-button:selected {
base-color: #ff6060;
}
.start-stop.toggle-button:hover {
-fx-background-color: derive(base-color, -20%);
}
If you cannot use derive since you need to specify different colors for all 4 states you could still rely on looked-up colors to avoid relying on the rule ordering:
.start-stop.toggle-button {
unselected-color: blue;
selected-color: yellow;
-fx-background-color: unselected-color;
}
.start-stop.toggle-button:hover {
unselected-color: red;
selected-color: green;
}
.start-stop.toggle-button:selected {
-fx-background-color: selected-color;
}

How to change the icon size of a color picker in JavaFX?

How to change the icon size of a color picker in javaFX. I'm having a problem, I can not increase the icon size of a color picker in JavaFX, does anyone know how to change the size of the button icon?
icon its small :(
Setting the CSS attributes -fx-color-rect-width and -fx-color-rect-width will change size of the rectangle displayed. Setting fx-font-size will change the size of the arrow.
Note that some of these attributes are not documented in the official JavaFX CSS reference, so I guess future JavaFX iterations could change them without notice. Still, at this stage, I think that is probably unlikely and the attributes are pretty safe to use. To determine the undocumented CSS attributes, I looked at the source code for the ColorPickerSkin.
pickme.css
.large-rect-picker {
-fx-color-rect-width: 60px;
-fx-color-rect-height: 60px;
-fx-color-label-visible: false;
-fx-min-width: 150px;
-fx-min-height: 100px;
-fx-pref-width: 150px;
-fx-pref-height: 100px;
}
.large-rect-picker > .arrow-button {
-fx-font-size: 30px;
}
PickMe.java
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ColorPicker;
import javafx.stage.Stage;
public class PickMe extends Application {
#Override
public void start(Stage stage) {
ColorPicker colorPicker = new ColorPicker();
colorPicker.getStyleClass().add("large-rect-picker");
stage.setScene(new Scene(new Group(colorPicker)));
stage.getScene().getStylesheets().add(
PickMe.class.getResource(
"pickme.css"
).toExternalForm()
);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Aside info on asking questions
It is difficult to know exactly what you want as you aren't really explicit in the question. For instance what do you mean by icon? The rectangle or the down arrow or both? What about the display that is popped up when you click on that arrow, should that change at all or stay the same? For future questions, I recommend you be more specific about what you are trying to achieve and how it differs from what you have. Showing code which produces what you have might also help others solve your issue. Hopefully the info above is enough for you to modify it to accomplish what you wish.
You can access and customize color picker by using css:
ColorPicker
Style class: color-picker
Substructure
color display node — Label
arrow-button — StackPane
arrow — StackPane
The ColorPicker control has all the properties and pseudo‑classes of ComboBase
Example
.color-picker .label {
-fx-background-color: red;
-fx-text-fill: null;
-fx-graphic: url("1487868456_Other_Antivirus_Software.png");//This is icon of Color picker label
}
Result:
As far as I know you cant use -fx-width/-fx-height at all and you cant use percentage values for it. The width and height of elements are read-only. You can set -fx-pref-width, -fx-pref-height, -fx-max-width, -fx-min-width, -fx-max-height, -fx-min-height ,-fx-border-width and -fx-border-height to adjust the size of Java FX elements.
.picker-color {
-fx-border-color:white ;
-fx-border-width:40;
}

Need to make transparent textview on gtk

Need to make transparent textview. Earlier I used gtk version 3.6.4 and made it using CSS file
GtkTextView{
font:Times New Roman, 20;
background:transparent;
}
Now I use gtk version 3.20.6 and make this css, font is changed (so css node is valid) but textview have white background, transparent doesn't work
textview{
font:Times New Roman, 20;
background:transparent;
}
If it's possible to make textview transparent using some code, it will also be good.
From the documentation for GtkTextView (emphasis mine):
GtkTextView has a main css node with name textview and style class .view, and subnodes for each of the border windows, and the main text area, with names border and text, respectively. The border nodes each get one of the style classes .left, .right, .top or .bottom.
Setting the text node under textview is what you need:
textview text {
font:Times New Roman, 20;
background:transparent;
}
Obviously, the textview part can be changed to whatever you need, for example #mytextviewid or .mytransparenttextviewclass so you can apply to a subset of all textviews using the style context.

How to lookup the applied font on JavaFX Label?

I need to automatically resize the font on my JavaFX Label if the text doesn't all fit in the label's boundaries. I found some awesome code online (here Resize JavaFX Label if overrun) to do this but the problem is the code takes font size and as an argument. It seems like determining the font size would be very easy, but Label.getFont() returns the default settings because my application is using css to set the font sizes. My css is setting the font size to 30, but everything I have figured out how to look up on the Label so far is returning default settings of 12.
So I tried looking it up but I don't understand where to look for it. Label.getStyle() returns an empty string. getCSSMetaData() returns a whole bunch of interesting settings and I was able to find font there and look at the sub properties, but again it is storing the default values of font size 12 and a different style name.
This is the setting from my style sheet file that I'm using so I know I need to locate feedback card and font size:
._Feedback_Card {
-fx-font-size: 30px;
-fx-font-weight: bold;
-fx-text-fill: rgba(0,0,0,.9);
-fx-background-color: white;
-fx-border-color: white;
-fx-border-width: 0;
-fx-alignment: center;
-fx-text-alignment: center;
-fx-font-family: Arial Unicode MS;
-fx-effect: dropshadow(gaussian, #b4b4b4, 6,0,0,2);
}
Don't be swayed by the name, there's a mapping somewhere else in the code that maps this component to that class name somehow. It's written by a co-worker so I'm unaware of the exact mechanics. But given that name I tried looking up the region on the root node with:
Region node = (Region)jsLayoutCollection.jsDisplayLayoutCollection.fGetFXParent().lookup("._Feedback_Card");
String sStream = node.getCssMetaData().stream()
and then I looked through the stream for font properties. But that again returned font but the size was the default 12, not 30 that the style sheet sets it to.
So where is this property being applied and how do I look it up? It seems like it should be straightforward to figure out this information but I can't find it. It's very easy to set the font after with:
Label.setStyle("-fx-font-size: " + fontSize + "px");
Any help is greatly appreciated.
Once the stylesheet has been loaded by the label's scene (or parent), and CSS has been applied, getFont() will return the font set by CSS.
This code:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class GetCSSFont extends Application {
#Override
public void start(Stage primaryStage) {
Label label = new Label("Big label");
StackPane root = new StackPane(label);
Scene scene = new Scene(root);
scene.getStylesheets().add("set-font.css");
System.out.println("Default font: "+label.getFont());
label.applyCss();
System.out.println("Font from CSS: "+label.getFont());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
with set-font.css:
.label {
/* Note the font family needs quoting if it has spaces: */
-fx-font-family: 'Arial Unicode MS' ;
-fx-font-size: 30px ;
-fx-font-weight: bold ;
}
.root {
-fx-padding: 20 ;
}
produces the output:
Default font: Font[name=System Regular, family=System, style=Regular, size=13.0]
Font from CSS: Font[name=Arial Unicode MS, family=Arial Unicode MS, style=Regular, size=30.0]
(And you can, of course, get the point size with double size = label.getFont().getSize().)

How can I add CSS effects to the 'Scene' of a JavaFX application?

I need to add a CSS effect to the 'scene' of a certain JavaFX application of mine, not a specific component of the scene or stage. I tried to use:
.main-scene{...}
and,
.main-class{...}
But neither worked.
CSS works on nodes not scenes.
There is a css class .root, which applies to the root node of all scenes in your application. For maximum flexibility, the root of the scene should be a Region subclass as regions have greater style options in JavaFX.
So for example, if you setup your primary stage like this.
Pane pane = new Pane();
pane.setId("my-pane");
stage.setScene(new Scene(pane, 300, 200));
Then you can style the root pane (of all scenes) using:
.root {
-fx-background-color: yellow;
}
Or just the specific root pane in the sample using:
#my-pane {
-fx-background-color: firebrick;
}
You can directly add the desired style to .root style class
From the docs
The .root style class is applied to the root node of the Scene
instance. Because all nodes in the scene graph are a descendant of the
root node, styles in the .root style class can be applied to any node.
The styles written inside this class doesn't need to be applied/added externally. Just add your style within the .root and it will be automatically picked up by javafx.
.root{
//Your styles
}
Though you need to externally add the css file !
scene.getStylesheets().add(
getClass().getResource("myCss.css").toExternalForm()
);

Resources