Method to change CSS subclass (choicebox item text color)

Asked

Viewed 1,029 times

2

I have a Choice-box. In my Choice-box there is a list of colors to be selected by the user through the interface. Every time the user selects a color, the background of that same Color Box gets the same color as the user selected. By default, the font color of the items in the Choice-box is white, but among the options for the user to choose, there is the white color... so when he selects "White", the Choice-box background also turns white... and as the default font is white, you already know... everything turns white, "no text".

Here as it stands:

Cor do background do choice-box e do texto brancos...

In the Stylesheet file, referring to what I said, the following:

.choice-box {
        -fx-background-color: black; 
        -fx-mark-color: #950005;
        -fx-border: 1px;
    }

    .choice-box > .label {
        -fx-text-fill: white;   
    }

Up there, as you can see, the font color of the Choice-box list item is set by default as white in the second class of CSS, that is, in the subclass "label" within the ". Choice-box".

When the guy selects a color item in the menu, the following action is executed in the "Onaction" of the Choice-box (after doing all the blablabla color checking):

choiceBox.setStyle("-fx-background-color: " + selectedColor + ";");

So far so good, the Choice-box changes color everything fillet, but I want to put the following condition, to avoid the white font on a light/white background:

if(selectedColor.equalsIgnoreCase(BRANCO)  || 
   selectedColor.equalsIgnoreCase(AMARELO) ||
   selectedColor.equalsIgnoreCase(CINZA)  || 
   selectedColor.equalsIgnoreCase(PRATA)) 
{
    //ação para fazer a cor da fonte do item selecionado no menu ser preta quando a cor selecionada pelo usuário for branca, amarela, cinza ou prata

}

But I’m not being able to access, through the java, this subclass ". label" that is inside the Choice-box. And you can’t create a @FXML Label meuLabel referencing to this text. You could do this if what I wanted to change was the label that is above each menu, saying what it is. The idea would be to do something like:

meuCoiceBox.getValue().setStyle("-fx-text-fill: black;");

or a

meuChoiceBox.getSelectionModel().getSelectedItem().setStyle("-fx-text-fill: black;");

...to change the color of the text this item with light background.

2 answers

3


In your case staying using setStyle has two disadvantages:

  1. It’s harder to keep in case of changes;
  2. There will be unnecessary code repetition.

I’ll put a solution here using external CSS, (if you’ve done it skip that part) first you create a Styles.css file in a package in your project (in the case below the default) and add that line in your main class:

Scene scene = new Scene(root, 300, 250);
scene.getStylesheets().add(this.getClass().getResource("styles.css").toString());

In the Styles.css file I did the following:

.root{ display: block;}
.corBranca{ -fx-background-color: white;}
.corAmarela{-fx-background-color: yellow;}

.corVermelha{-fx-background-color: red;}
.corVermelha .label{ -fx-text-fill: white;}
.corVermelha .context-menu .label{-fx-text-fill: black;}

.corVerde{-fx-background-color: green;}
.corVerde .context-menu .label{-fx-text-fill: black;}
.corVerde .label{ -fx-text-fill: white;}

I had to change the color of the menu context to black where the default letter is white (you changed the text-Fill from any Component to white)

Here is the java code for color change:

ChoiceBox<String> choice = new ChoiceBox();
ObservableList<String> choices = FXCollections.observableArrayList();
choices.addAll("corAmarela","corBranca", "corVermelha", "corVerde");
choice.setItems(choices);

choice.getSelectionModel().selectedItemProperty().addListener((ObservableValue<? extends String> ov, String t, String t1) -> {
    choice.getStyleClass().setAll(t1);
});

I put the name of the choicebox items equal to css so I don’t have to do if-Lse but it’s not required. The getStyleClass() method tells you what the class of the component is, it works like normal css when we make class="suaClasse".

The result is this:

inserir a descrição da imagem aqui

Just one more tip: prefer to use the HEX codes of the colors instead of the shortcuts (white, red, etc) I put them only for didactic questions.

  • Sorry it took me so long to give you feedback. I haven’t been able to make it work yet... I must be doing something wrong. As soon as I get it, I’ll let you know. Thank you for the reply!

  • I think it is conflicting with the "fx:Id" that I have set for each menu of this. I can set an id pro css and another pro fx ?

  • You didn’t tell me you were using FXML, I’m changing to suit the answer.

  • In fact, I managed to make it work in parts... It only works properly the first time I choose a color from the menu. Every time you change the menu color, the menu onAction calls a method that changes the color of a rectangle (which sits on an image of a resistor). However, this method takes a choicebox type parameter, and saves the name of the menu id before going to a switch-case where it "asks" the name of the interacted menu and the selected color and changes the color of the rectangle. After I interact the first time, the menu gets another id (to change the css id) and the rectangle stops changing color..

  • I edited taking out the conflict of Ids, look at the code and css again.

  • I put down my final solution. I ended up changing some things, but the main thing was to have learned the use of this method "setStyleClass()". Thanks!

Show 1 more comment

1

I needed to answer my own question instead of commenting on the answer above, because I wanted to show my final solution, which was too big to put in a comment there...

SOLUTION:

When the user selects a color in the Choice-box, a method is called where I save the color in a variable called "selectedColor" and , after a switch-case to change the rectangle color and change the resistance value (so far nothing different than what was already), put the following if-lse:

if(selectedColor.equalsIgnoreCase(BRANCO) || selectedColor.equalsIgnoreCase(AMARELO) || 
       selectedColor.equalsIgnoreCase(CINZA) || selectedColor.equalsIgnoreCase(PRATA)) {
  choiceBox.getStyleClass().setAll("choice-box","itemCorClara");
} else {
  choiceBox.getStyleClass().setAll("choice-box","itemCorEscura");
}

I didn’t use the addListener because I didn’t think it was necessary. I don’t even know if my way got more "ugly" or out of pattern, but I found it easier to understand what I did there.

When I choose the class according to the color, there in this if-Else, I actually set 2 classes pro Choice-Box, being a "base class" (Choice-box) and one with the "customization" that I wanted (itemCorClara or itemCorEscura), getting my CSS file so:

.choice-box {
    -fx-background-color: black; 
    -fx-mark-color: #950005;
}

.choice-box .label {
    -fx-text-fill: white;   
}

.choice-box .context-menu {
    -fx-background-color: #666666;    
}

.choice-box .menu-item:focused {
    -fx-background-color: #950005;   
}

.choice-box .menu-item > .label {
    -fx-text-fill: black;   
}

.choice-box .menu-item:focused > .label {
    -fx-text-fill: white;   
}

/*#####################################*/

.itemCorEscura .label {
    -fx-text-fill: white;   /
}

/*######################################*/

.itemCorClara .label {
    -fx-text-fill: #000000;   
}

And, I continued using setStyle to change only the background of Choice-box, because I thought better than creating a class for each color. My question is only whether it really looks better with setStyle or if creating a class for each color even. Or it’s just a matter of personal taste?

choiceBox.setStyle("-fx-background-color: " + traduzirCor(choiceBox.getValue()) + "; -fx-mark-color: #950005;");

This method "translate Cor(choiceBox.getValue())" I used is just one I did to return a color name "understandable" by css, since the value received from Choice-box is the name of the color in Portuguese (Ex.: "WHITE").

Just so I could really leave everything 100%, until then there was always something going wrong.

Thanks for the HUGE help, Gustavo, I learned a lot from yesterday to today! All notes noted!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.