0

I want load my custom component in my fxml file directly. But I have an error when I run my example.

MyFXML

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.RowConstraints?>
<?import br.com.prati.collaboration.iem.components.PratiLabel?>
<?import javafx.geometry.Insets?>
<?import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon?>
<?import br.com.prati.collaboration.iem.components.FillEmoticon?>
<?import java.lang.*?>
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="br.prati.tim.collaboration.iem.view.MetasDisplay" style="-fx-background-color: white;" prefWidth="800" prefHeight="600">
  <padding>
    <Insets top="8" left="5" right="5" />
  </padding>
  <GridPane>
    <columnConstraints>
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="400.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
    </columnConstraints>
    <rowConstraints>
      <RowConstraints vgrow="SOMETIMES" minHeight="10" />
      <RowConstraints vgrow="SOMETIMES" minHeight="10" />
    </rowConstraints>
    <children>
      <PratiLabel title="Lote Programado" GridPane.rowIndex="0" GridPane.columnIndex="0" />
      <PratiLabel title="Lote Realizado" GridPane.rowIndex="1" GridPane.columnIndex="0" />
      <PratiLabel fx:id="statusPane" title="Status Lote" GridPane.rowIndex="0" GridPane.columnIndex="1" GridPane.rowSpan="2" alignment="CENTER">
        <nodes>
          <FillEmoticon sizeEM="10" fill="YELLOW" />
        </nodes>
      </PratiLabel>
    </children>
  </GridPane>
</VBox>

snippet fxml with my custom component FillEmoticon

...
<nodes>
  <FillEmoticon sizeEM="10" fill="YELLOW"/>
</nodes>

class

package br.com.prati.collaboration.iem.components;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import de.jensd.fx.glyphs.GlyphIcon;
import de.jensd.fx.glyphs.GlyphsBuilder;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcons;

public class FillEmoticon extends StackPane {

    private static final double SCALE_EM_TO_PX = 4.5;

    private GlyphIcon<?> icon;
    private Circle filled;

    private double sizeEM = 4.5;

    public FillEmoticon() {


        String iconStyle = "-fx-font-size: 4em; -fx-fill: black; -fx-stroke-width: 2px;";

        icon = GlyphsBuilder.create(FontAwesomeIcon.class)
                .glyph(FontAwesomeIcons.SMILE_ALT)
                .style(iconStyle)
                .build();

        filled = new Circle( 4 * sizeEM, Paint.valueOf("GREEN"));

        getChildren().addAll(filled, icon);

    }

    public void setName(String name){
        this.icon.setGlyphName(name);
    }

    public void setFill(String paint){
        filled.setFill(Paint.valueOf(paint));
    }

    public String getFill(String paint){
        return filled.getFill().toString();
    }

    public void setSizeEM(double value){
        icon.setStyle("-fx-font-size: " + value + "em; -fx-font-family: Fontawesome;");
        filled.setRadius(value * SCALE_EM_TO_PX);
    }

    public double getSizeEM(){
        return sizeEM;
    }

}

error when I run

    Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$152(LauncherImpl.java:182)
    at com.sun.javafx.application.LauncherImpl$$Lambda$50/1463801669.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: 
/C:/externo/Iem/inspecao.embalagem-jar/target/classes/fxml/Metas.fxml:37

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2605)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2583)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2445)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3218)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3128)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3108)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3101)
    at br.prati.tim.collaboration.iem.view.MetasDisplay.start(MetasDisplay.java:30)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159(LauncherImpl.java:863)
    at com.sun.javafx.application.LauncherImpl$$Lambda$53/606827964.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl$$Lambda$45/1681433494.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$170(PlatformImpl.java:295)
    at com.sun.javafx.application.PlatformImpl$$Lambda$48/1144405258.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(PlatformImpl.java:294)
    at com.sun.javafx.application.PlatformImpl$$Lambda$47/1685538367.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(WinApplication.java:101)
    at com.sun.glass.ui.win.WinApplication$$Lambda$36/2058534881.run(Unknown Source)
    ... 1 more
Caused by: com.sun.javafx.fxml.PropertyNotFoundException: Property "fill" does not exist or is read-only.
    at javafx.fxml.FXMLLoader$Element.processValue(FXMLLoader.java:344)
    at javafx.fxml.FXMLLoader$Element.processPropertyAttribute(FXMLLoader.java:321)
    at javafx.fxml.FXMLLoader$Element.processInstancePropertyAttributes(FXMLLoader.java:231)
    at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:763)
    at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2827)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2536)
    ... 22 more
Exception running application br.prati.tim.collaboration.iem.view.MetasDisplay

Whats is the problem with my custom component ?

1 Answer 1

2

I'm not sure why, but it seems you need to structure it like this:

public class FillEmoticon {

    public StringProperty fill = new SimpleStringProperty();

    public StringProperty fillProperty() {
        return fill ;
    }

    public final String getFill() {
        return fillProperty().get();
    }

    public final void setFill(String fill) {
        fillProperty().set(fill);
    }

    public FillEmoticon() {
        // ...
        fill.addListener((obs, oldFill, newFill) -> filled.setFill(Paint.valueOf(newFill)));

    }

    // ...
}

and then in the FXML you have to use a property element, instead of an attribute:

<FillEmoticon>
    <fill>YELLOW</fill>
</FillEmoticon>

Note that since Paint has a valueOf method, you can access it directly, instead of indirectly through a String. This makes things a bit easier:

public class FillEmoticon {

    // code exactly as you have, except for get/setFill

    public ObjectProperty<Paint> fillProperty() {
        return filled.fillProperty();
    }

    public final void setFill(Paint fill) {
        fillProperty().set(fill);
    }

    public final Paint getFill() {
        return fillProperty().get();
    }

}

and then your current FXML seems to work.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.