1

I'm having an issue where I need javafx to update a Label's widthProperty immediately after changing the text in that Label. It appears after changing after changing text it takes the application an additional cycle to update the width of that Label.

Specifically I have a custom color picker object, which has Label with the color hex value laid on top of a Circle, with a hidden ColorPicker behind both of them.

I want to update this object when the value of the color picker changes. The problem however is that when I try to rescale the Label, the old width property is used causing it to scale incorrectly:

   colorPicker.valueProperty().addListener((Observable e) ->{
        circle.setFill(colorPicker.getValue());
        colorText.setText(colorPicker.getValue().toString());
        colorText.setTextFill(colorPicker.getValue().invert());

        //The values are set before the function call, but the width isn't updated
        scaleText();
    });

.

private void scaleText(){
    colorText.applyCss(); //I was hoping this line would force an update, but no dice
    if(circle.getRadius() == 0d || colorText.getWidth() == 0d){
        return;
    }
    //The following line of code will use the old width property
    double scale = (circle.getRadius()*1.60)/colorText.getWidth();
    colorText.setScaleX(scale);
    colorText.setScaleY(scale);
}

I know that this is the value not being updated immediately because I was able to 'fix' the issue by running scaleText() after a delay from another thread:

new Thread(() -> {
            try {
                Thread.sleep(25);
            } catch (InterruptedException ex) {
                Logger.getLogger(ColorPickerCircle.class.getName()).log(Level.SEVERE, null, ex);
            }
            scaleText();
        }).start();

However I would like to find a solution that doesn't rely on delaying the function call from another thread. So my question boils down to: Is there any way to force an immediate widthProperty update?

luckydog32
  • 909
  • 6
  • 13
  • What's the `applyCss()` function doing? – AntJavaDev Nov 12 '17 at 17:32
  • Try calling `layout()` in addition to `applyCSS()` on the *parent* of the label. – James_D Nov 12 '17 at 17:34
  • @AntJavaDev Currently it doesn't appear to be doing anything, I saw that it was recommended sometimes to apply styling before initialization. But it doesn't perform any action in this code at the moment, it was just a shot in the dark at bug fixing by me. – luckydog32 Nov 12 '17 at 17:34
  • @James_D I will give it a shot, but the parent is the custom `StackPane` object that all these functions/objects are a part of, and it is height and width properties are locked. – luckydog32 Nov 12 '17 at 17:36
  • @James_D Thank you for the suggestion, but it unfortunately did not work. – luckydog32 Nov 12 '17 at 17:39
  • Well, `layout()` should lay out the stack pane regardless of that. It sounds as though you are really fighting against using the API in the way it was designed here. Perhaps you need to rethink you strategy from a higher-level view. – James_D Nov 12 '17 at 17:39
  • I suggest you create a [MCVE]. – James_D Nov 12 '17 at 17:40
  • @James_D Actually layout does appear to be functioning, thank you. If you make it an answer to this question I will accept it as the answer. If you have any suggestions as to how to make the question more complete I would be happy to add them into the question. – luckydog32 Nov 12 '17 at 17:45
  • @luckydog32 tbh I don't really want to encourage others to use this kind of approach, as I don't think it's really appropriate for a site aimed at professional programmers. – James_D Nov 12 '17 at 17:47
  • @James_D What would be a better approach? – luckydog32 Nov 12 '17 at 17:47
  • I don't know what you're trying to do, but it sounds like you are making something like a custom control. If so, you should design it like the standard controls, with a skin class that extends skin base and overrides the usual layout methods to size and position the child nodes. – James_D Nov 12 '17 at 17:55

0 Answers0