JavaFX Custom BarChart - Unable to instantiate

Viewed 52

I've extended the BarChart Component in my CustomBarChart to add Labels to the Bars. However, when trying to execute it, I get this Error. Meaning it's unable to instantiate, clueless on what seems to be the Problem / what I'm missing here.

Thanks in Advance.

Error

javafx.fxml.LoadException: 

/C:/Users/mpich/IdeaProjects/Unfallmeldung/target/classes/com/pichlmayr/unfallmeldung/analyseAccidents.fxml:13

    at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2707)
    at javafx.fxml/javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1022)
    at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:757)
    at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2808)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2634)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2516)
    at com.pichlmayr.unfallmeldung@0.6-SNAPSHOT/com.pichlmayr.unfallmeldung.SceneManager.loader(SceneManager.java:19)
    at com.pichlmayr.unfallmeldung@0.6-SNAPSHOT/com.pichlmayr.unfallmeldung.ShowAccidents.onEvaluate(ShowAccidents.java:158)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:77)
    at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:84)
    at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1852)
    at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1724)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8792)
    at javafx.controls/javafx.scene.control.Button.fire(Button.java:203)
    at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:208)
    at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3897)
    at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1878)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2623)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
    at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:557)
    at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:943)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NoSuchMethodException: com.pichlmayr.unfallmeldung.CustomBarChart.<init>()
    at java.base/java.lang.Class.getConstructor0(Class.java:3585)
    at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2754)
    at javafx.fxml/javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1020)
    ... 64 more

CustomBarChart.java

package com.pichlmayr.unfallmeldung;

import javafx.scene.Node;
import javafx.scene.chart.Axis;
import javafx.scene.chart.BarChart;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import javafx.scene.text.TextFlow;

import java.util.HashMap;
import java.util.Map;

public class CustomBarChart<X, Y> extends BarChart<X, Y> {
    Map<Node, TextFlow> nodeMap = new HashMap<>();

    public CustomBarChart(Axis xAxis, Axis yAxis) {
        super(xAxis, yAxis);
        this.setBarGap(0.0);
    }

    @Override
    protected void seriesAdded(Series<X, Y> series, int seriesIndex) {
        super.seriesAdded(series, seriesIndex);
        for (int j = 0; j < series.getData().size(); j++) {

            Data<X, Y> item = series.getData().get(j);

            Text text = new Text(item.getYValue().toString());
            text.setStyle("-fx-font-family: Arial;");
            text.setStyle("-fx-font-size: 8pt;");
            
            TextFlow textFlow = new TextFlow(text);
            textFlow.setTextAlignment(TextAlignment.CENTER);

            nodeMap.put(item.getNode(), textFlow);
            this.getPlotChildren().add(textFlow);

        }
    }

    @Override
    protected void seriesRemoved(final Series<X, Y> series) {
        for (Node bar : nodeMap.keySet()) {
            Node text = nodeMap.get(bar);
            this.getPlotChildren().remove(text);
        }

        nodeMap.clear();

        super.seriesRemoved(series);
    }

    @Override
    protected void layoutPlotChildren() {
        super.layoutPlotChildren();
        for (Node bar : nodeMap.keySet()) {

            TextFlow textFlow = nodeMap.get(bar);

            if (bar.getBoundsInParent().getHeight() > 30) {
                ((Text) textFlow.getChildren().get(0)).setFill(Color.WHITE);
                textFlow.resize(bar.getBoundsInParent().getWidth(), 200);
                textFlow.relocate(bar.getBoundsInParent().getMinX(), bar.getBoundsInParent().getMinY() + 10);
            } else {
                ((Text) textFlow.getChildren().get(0)).setFill(Color.GRAY);
                textFlow.resize(bar.getBoundsInParent().getWidth(), 200);
                textFlow.relocate(bar.getBoundsInParent().getMinX(), bar.getBoundsInParent().getMinY() - 20);
            }
        }
    }
}

analyzeAccident.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import com.pichlmayr.unfallmeldung.CustomBarChart?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane fx:id="mainAnchor" prefHeight="800.0" prefWidth="1200.0" styleClass="mainAnchor"
            stylesheets="@styleshees.css" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"
            fx:controller="com.pichlmayr.unfallmeldung.AnalyzeAccident">
    <children>
        <CustomBarChart fx:id="course" layoutX="25.0" layoutY="70.0" prefHeight="720.0" prefWidth="1161.0"
                        visible="false">
            <xAxis>
                <CategoryAxis fx:id="Category" side="BOTTOM"/>
            </xAxis>
            <yAxis>
                <NumberAxis fx:id="Number" side="LEFT"/>
            </yAxis>
        </CustomBarChart>
        <CustomBarChart fx:id="courseTimespan" layoutX="25.0" layoutY="70.0" prefHeight="710.0" prefWidth="1161.0"
                        visible="false">
            <xAxis>
                <CategoryAxis fx:id="CategoryTimespan" side="BOTTOM"/>
            </xAxis>
            <yAxis>
                <NumberAxis fx:id="NumberTimespan" side="LEFT"/>
            </yAxis>
        </CustomBarChart>
        <MenuButton layoutX="24.0" layoutY="14.0" mnemonicParsing="false" styleClass="actionButton"
                    stylesheets="@styleshees.css" text="Auswertungjahr">
            <items>
                <MenuItem mnemonicParsing="false" onAction="#onYearAll" text="Alle"/>
                <MenuItem mnemonicParsing="false" onAction="#onYearTimespan" text="2019-2022"/>
                <MenuItem mnemonicParsing="false" onAction="#onYear2019" text="2019"/>
                <MenuItem mnemonicParsing="false" onAction="#onYear2020" text="2020"/>
                <MenuItem mnemonicParsing="false" onAction="#onYear2021" text="2021"/>
                <MenuItem mnemonicParsing="false" onAction="#onYear2022" text="2022"/>
            </items>
        </MenuButton>
        <MenuButton layoutX="240.0" layoutY="14.0" mnemonicParsing="false" styleClass="actionButton"
                    stylesheets="@styleshees.css" text="Auswertung">
            <items>
                <MenuItem mnemonicParsing="false" onAction="#perMonth" text="Unfälle pro Monat"/>
                <MenuItem mnemonicParsing="false" onAction="#perWeekday" text="nach Wochentag"/>
                <MenuItem mnemonicParsing="false" onAction="#perLocation" text="pro Arbeitsplatz"/>
                <MenuItem mnemonicParsing="false" onAction="#perInjuryType" text="nach Unfallart"/>
                <MenuItem mnemonicParsing="false" onAction="#perInjuredBodyPart" text="nach Verletzung"/>
            </items>
        </MenuButton>
        <Button fx:id="export" layoutX="412.0" layoutY="14.0" mnemonicParsing="false" onAction="#onExport"
                styleClass="actionButton" stylesheets="@styleshees.css" text="Exportieren"/>
        <Button fx:id="back" layoutX="1099.0" layoutY="14.0" mnemonicParsing="false" onAction="#onBack"
                styleClass="actionButton" stylesheets="@styleshees.css" text="Zurück"/>
    </children>
</AnchorPane>

Declaration of the CustomBarChart

@FXML
public CustomBarChart<String, Number> course;
@FXML
public CustomBarChart<String, Number> courseTimespan;
1 Answers

Fixed it by adding a default constructor.

@NamedArgs is required so the xAxis and yAxis get recognized.

public CustomBarChart() {
    super((Axis<X>) new CategoryAxis(), (Axis<Y>) new NumberAxis());
}

public CustomBarChart(@NamedArg("xAxis") Axis xAxis, @NamedArg("yAxis") Axis yAxis) {
    super(xAxis, yAxis);
    this.setBarGap(0.0);
}
Related