Method to change CSS subclass (color of the item text in the choicebox)

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 choice-box is the same color that the user selected. By default, the font color of the items in the choice-box is white, but among the options the user chooses, there is a white color ... so when he selects "White", the bottom of the choice box also turns white ... and as the default font is white, you know ... everything is white, "without text".

Here's how:

IntheStyleSheetfile,Ihavethefollowing:

.choice-box{-fx-background-color:black;-fx-mark-color:#950005;-fx-border:1px;}.choice-box>.label{-fx-text-fill:white;}

Upthere,asyoucansee,thefontcolorofthechoice-boxlistitemissetbydefaulttowhiteinthesecondCSSclass,thatis,inthe"label" subclass, within ".choice- box. "

When the guy selects a color item from the menu, the following action is performed on the choice-box's "OnAction" (after doing all the blablabla color checking):

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

So far so good, the choice-box changes everything fillet color, 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 able to access, by java, this subclass ".label" that is inside the choice-box. And you can not create a @FXML Label meuLabel referencing this text. I would have to do this if what I wanted to change was the Label that stands above each menu, saying what it is. The idea would be to do something like this:

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

or one

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

... to change the text color of this item with a clear background.

    
asked by anonymous 15.10.2017 / 01:18

2 answers

3

In your case using setStyle has two drawbacks:

  • More difficult to maintain in case of changes;
  • There will be repetition of unnecessary code.
  • I'll put a solution here using external CSS, ( if you've already done that skip ) first you create a styles.css file in a package in your project in the case below the default) and add this 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 context menu to black where the default letter is white (you changed the text-fill of all the 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 items of the choicebox equal to css so I do not have to do if-else but it is not mandatory. The getStyleClass () method says which class is the component, works just like in the normal css when we do class="yourClass".

    The result is this:

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

        
    15.10.2017 / 03:16
    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 into 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 color of the rectangle and change the value of the > (so far nothing other than what I already was) , I put the following if-else:

    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 did not use the addListener because I did not find it necessary. I do not know if my way got any more "ugly" or out of standard, but I found it easier to understand what I did there.

    When I set the class according to the color, there in this if-else, I actually have two classes for the Choice-Box, being a "base-class" (choice-box) and one with "customization "which I wanted (itemCorClara or itemCorEscura), getting my CSS file like this:

    .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 kept using setStyle to change only the background of the choice-box, because I thought it was better than creating a class for each color. My question is only if it really gets better with setStyle or if you create a class for each color yourself. Or is it just a matter of personal taste?

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

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

    Just like that, I really managed to leave everything 100%, until then I always had something wrong going wrong.

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

        
    17.10.2017 / 01:57