Tornadofx: Third-party components in TornadoFx

Created on 7 Nov 2017  路  13Comments  路  Source: edvin/tornadofx

Hi, I've been meeting TornadoFx and I think it's a great project, I plan to migrate some applications that I have to TornadoFx.

I like the fact of creating a user interface with a class in Kotlin, but I ran into a problem, I use JFoenix and I would like to know if there are ways to create the user interface using Kotlin classes. Since I see that they have a better potential. I want to stop using .fxml, which brings me a headache.

class LoginScreen :View(){
    override val root = StackPane()

    init {
        title = "Login"

        with(root){

            vbox {
                hbox {
                    label("Name:")
                    jfxTextField() // <-------- this gives error - Component JFoenix
                    }
                }
            }

        }
    }
}

Thank you

Most helpful comment

Questions are always welcome, and especially as issues, since they become searchable for others :)

All 13 comments

You can create the jfxTextField builder the same way we create our builders, but you can also add components by creating them manually:

this += JFXTextField().apply {
 // Configure the textfield here
}

Great, are there limitations when creating components in this way? Or can I take advantage of all the features like using a "text field" of tornadofx?

I am trying tornadofx, and I would like to know how I can use the css of a third party component, for example:

vbox {
         minWidth = 350.0
         hgrow = Priority.ALWAYS
         hbox {
              alignment = Pos.CENTER_LEFT
              minHeight = 40.0
              this += JFXButton("_").apply {
                   addClass(buttonBoxHeader)
             }
        }
}

And the css where is the error is this:

class Styles : Stylesheet() {

    companion object {
        val buttonBoxHeader by cssclass()
    }

    init {
        s(buttonBoxHeader) {
            ripplerFill = Color.WHITE // does not recognize the ripplerFill property of the JFXButton.
        }
    }
}

Any solution for this case, using a stylesheet?.

You have to use custom properties for that:

class Styles : Stylesheet() {
    companion object {
        val buttonBoxHeader by cssclass()
        val ripplerFill by cssproperty<Color>()  // Or whatever type your property is
    }

    init {
        buttonBoxHeader {
            ripplerFill.value = c("dodgerblue")
        }
    }
}

It's a little hackish, but it works. Eventually we'll have a better solution when we make custom stylesheet bases work, but that's a ways out on the roadmap.

(Also note that you don't need to wrap buttonBoxHeader with s. You really only need s to have multiple selections.)

Thanks, I'm already understanding the world of TornadoFx. But I found a problem. Some JFXTextfield that I use must be validated and I do it this way with JavaFx without TornadoFx:

JFXTextField validationField = new JFXTextField();
validationField.setPromptText("With Validation..");
        RequiredFieldValidator validator = new RequiredFieldValidator();
        validator.setMessage("Input Required");
        validator.setIcon(GlyphsBuilder.create(FontAwesomeIconView.class)
            .glyph(FontAwesomeIcon.WARNING)
            .size(EM1)
            .styleClass(ERROR)
            .build());
validationField.getValidators().add(validator);

or with FXML:

<JFXTextField fx:id="validationField" labelFloat="true" promptText="With Validation.." >
         <validators>
            <RequiredFieldValidator message="Input Required!">
                        <FontAwesomeIconView glyphName="WARNING" style="-fx-font-family: FontAwesome;"/>
           </RequiredFieldValidator>
         </validators>
</JFXTextField>

And I activate it with the following code line

validationField.focusedProperty().addListener((o, oldVal, newVal) -> {
            if (!newVal) {
                validationField.validate();
            }
});

How could that validation function pass to TornadoFx?

Thanks for the answers.

I would recommend skipping the JPhoenix validation and use TornadoFX validation instead, but if you want to go this route, you can easily do that as well. The same code in Kotlin would be:

validationField.focusedProperty().onChange {
    if (!it) validationField.validate()
}

Thanks for the reply, but with the new component it does not allow me to do that functio:

this += JFXTextField().apply {
     isLabelFloat = true
     promptText = "Usuario"
}.focusedProperty().onChange { if (!it) validationField.validate() } // error when adding this method

Any example of how to do it?
And also how to add the validator to JFXTextField?
Thank you

Put it inside the apply block, and please post the error message instead of just "error" :)

You're trying to add the results of onChange { ... } to this. You need to move that call into the block:

this += JFXTextField().apply {
    isLabelFloat = true
    promptText = "Usuario"
    focusedProperty().onChange { if (!it) validationField.validate() }
}

@edvin Ah, you are quicker :)

@ruckustboom I try to beat you whenever there is no css involved 馃槅

Thank you very much for everything, and I have learned a lot with your help plus the TornadoFx documentation. I will try not to ask more silly questions :sweat_smile: .
Thanks again and regards.

Questions are always welcome, and especially as issues, since they become searchable for others :)

Was this page helpful?
0 / 5 - 0 ratings