2

In java 8 it states Builders are deprecated: http://mail.openjdk.java.net/pipermail/openjfx-dev/2013-March/006725.html

I am trying to extend a chart to add Horizontal and Vertical Markers to the chart. In this case I am extending LineChart. I wish to use said LineChart in FXML which begins throwing: java.lang.NoSuchMethodException: ...chart.LineChartWithMarkers.() this is caused by there not being a Default constructor.

Since Linechart's constructor Takes 2 Arguments for XAxis and YAxis, and builders are deprecated. How am I supposed to get FXML to be able to load my class, or did I miss something big?

I really want to Generalize this for any class that extends Node that does not have a default constructor, and working on the Java 8 (8u40+) FXML libraries. I have yet to find a definitive answer to this. All i hear is builders are being deprecated and removed completely in JDK9 but no solution to what supersedes them or what method you need to override to get this to work, if you are using it in FXML.

From what I can Tell the old way the builders would not make an instance of the class until any required fields were added.

Hopefully someone will chime in and show me what I've missed.

Java Class for Custom Chart

package custom.chart;

import java.util.Objects;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.chart.Axis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.ValueAxis;
import javafx.scene.shape.Line;

public class LineChartWithMarkers<X,Y> extends LineChart<X, Y> {

    @FXML
    protected ObservableList<Data<X,Y>> hzMarkers;
    @FXML
    protected ObservableList<Data<X,Y>> vtMarkers;

    public LineChartWithMarkers(Axis<X> arg0, Axis<Y> arg1) {
        super(arg0, arg1);

        hzMarkers = FXCollections.observableArrayList( d -> new Observable[] { d.YValueProperty() });
        vtMarkers = FXCollections.observableArrayList( d -> new Observable[] { d.XValueProperty() });

        hzMarkers.addListener( (InvalidationListener)observable -> layoutPlotChildren() );
        vtMarkers.addListener( (InvalidationListener)observable -> layoutPlotChildren() );

    }



    public LineChartWithMarkers(Axis<X> arg0, Axis<Y> arg1,
            ObservableList<javafx.scene.chart.XYChart.Series<X, Y>> arg2) {
        super(arg0, arg1, arg2);

        hzMarkers = FXCollections.observableArrayList( d -> new Observable[] { d.YValueProperty() });
        vtMarkers = FXCollections.observableArrayList( d -> new Observable[] { d.XValueProperty() });

        hzMarkers.addListener( (InvalidationListener)observable -> layoutPlotChildren() );
        vtMarkers.addListener( (InvalidationListener)observable -> layoutPlotChildren() );
    }



    @Override
    protected void layoutPlotChildren() {
        super.layoutPlotChildren();
        for (Data<X, Y> horizontalMarker : hzMarkers) {
            double lower = ((ValueAxis<?>) getXAxis()).getLowerBound();
            X lowerX = getXAxis().toRealValue(lower);
            double upper = ((ValueAxis<?>) getXAxis()).getUpperBound();
            X upperX = getXAxis().toRealValue(upper);
            Line line = (Line) horizontalMarker.getNode();
            line.setStartX(getXAxis().getDisplayPosition(lowerX));
            line.setEndX(getXAxis().getDisplayPosition(upperX));
            line.setStartY(getYAxis().getDisplayPosition(horizontalMarker.getYValue()));
            line.setEndY(line.getStartY());
        }
        for (Data<X, Y> verticalMarker : vtMarkers) {
            double lower = ((ValueAxis<?>) getYAxis()).getLowerBound();
            Y lowerY = getYAxis().toRealValue(lower);
            double upper = ((ValueAxis<?>) getYAxis()).getUpperBound();
            Y upperY = getYAxis().toRealValue(upper);
            Line line = (Line) verticalMarker.getNode();

            line.setStartX(getXAxis().getDisplayPosition(verticalMarker.getXValue()));
            line.setEndX(line.getStartX());
            line.setStartY(getYAxis().getDisplayPosition(lowerY));
            line.setEndY(getYAxis().getDisplayPosition(upperY));

        }
    }

    /**
     * Add horizontal value marker. The marker's Y value is used to plot a
     * horizontal line across the plot area, its X value is ignored.
     * 
     * @param marker must not be null.
     */
    public void addHorizontalValueMarker(Data<X, Y> marker) {
        Objects.requireNonNull(marker, "the marker must not be null");
        if (hzMarkers.contains(marker)) return;
        Line line = new Line();
        marker.setNode(line );
        getPlotChildren().add(line);
        hzMarkers.add(marker);
    }

    public void removeHorizontalValueMarker(Data<X, Y> marker) {
        Objects.requireNonNull(marker, "the marker must not be null");
        if (marker.getNode() != null) {
            getPlotChildren().remove(marker.getNode());
            marker.setNode(null);
        }
        hzMarkers.remove(marker);
    }

    public void addVerticalValueMarker(Data<X, Y> marker) {
        Objects.requireNonNull(marker, "the marker must not be null");
        if (hzMarkers.contains(marker)) return;
        Line line = new Line();
        marker.setNode(line );
        getPlotChildren().add(line);
        vtMarkers.add(marker);
    }

    public void removeVerticalValueMarker(Data<X, Y> marker) {
        Objects.requireNonNull(marker, "the marker must not be null");
        if (marker.getNode() != null) {
            getPlotChildren().remove(marker.getNode());
            marker.setNode(null);
        }
        vtMarkers.remove(marker);
    }


}

And the FXML

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

<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.chart.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import custom.chart.*?>

<fx:root maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="768.0" prefWidth="1024.0" type="VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <HBox prefHeight="100.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
         <children>
            <StackPane prefHeight="150.0" prefWidth="200.0" HBox.hgrow="ALWAYS">
               <children>
                  <Group>
                     <children>
                        <ProgressIndicator fx:id="prg" progress="0.0" />
                     </children>
                  </Group>
                  <LineChartWithMarkers fx:id="chart" createSymbols="false" horizontalZeroLineVisible="false" opacity="1" title="Heater Data" verticalZeroLineVisible="false">
                    <xAxis>
                      <NumberAxis forceZeroInRange="false" side="BOTTOM" fx:id="xAxis" />
                    </xAxis>
                    <yAxis>
                      <NumberAxis fx:id="yAxis" forceZeroInRange="false" side="LEFT" />
                    </yAxis>
                  </LineChartWithMarkers>
               </children>
            </StackPane>
            <TableView fx:id="tblChartOptions" editable="true" prefHeight="513.0" prefWidth="299.0">
              <columns>
                  <TableColumn fx:id="txSelect" prefWidth="34.0" text="X" />
                <TableColumn fx:id="tcName" editable="false" prefWidth="143.0" text="Value" />
                <TableColumn fx:id="tcStyle" prefWidth="61.0" text="Style" visible="false" />
                  <TableColumn fx:id="tcDisplayName" prefWidth="113.0" text="Display Name" />
              </columns>
            </TableView>
         </children>
      </HBox>
      <HBox alignment="BOTTOM_LEFT" nodeOrientation="RIGHT_TO_LEFT" prefWidth="200.0">
         <children>
            <Button fx:id="btnSaveChart" mnemonicParsing="false" onAction="#onSaveChart" text="Save Image" HBox.hgrow="ALWAYS" />
            <GridPane prefWidth="320.0">
              <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
              </columnConstraints>
              <rowConstraints>
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
              </rowConstraints>
               <children>
                  <Label text="X Axis Title" GridPane.columnIndex="1" GridPane.rowIndex="1" />
                  <Label text="Y Axis Title" GridPane.columnIndex="1" GridPane.rowIndex="2" />
                  <TextField fx:id="txtXaxis" nodeOrientation="LEFT_TO_RIGHT" text="Time" GridPane.halignment="LEFT" GridPane.rowIndex="1" />
                  <TextField fx:id="txtYaxis" nodeOrientation="LEFT_TO_RIGHT" text="Temp (C)" GridPane.halignment="LEFT" GridPane.rowIndex="2" />
                  <CheckBox fx:id="cbIgnoreZeroValues" mnemonicParsing="false" onAction="#onZeroChangeState" text="IgnoreZeros" GridPane.columnIndex="1" GridPane.rowIndex="3" />
                  <Label text="Chart Title" GridPane.columnIndex="1" />
                  <TextField fx:id="txtChartTitle" nodeOrientation="LEFT_TO_RIGHT" text="Heater Data" />
               </children>
            </GridPane>
         </children>
      </HBox>
   </children>
</fx:root>
assylias
  • 321,522
  • 82
  • 660
  • 783
bghost4
  • 21
  • 5
  • I think http://stackoverflow.com/questions/26823157/what-is-the-purpose-of-namedarg-annotation-in-javafx-8 answers this. And, yes, the documentation is completely lacking: you might want to vote for [this](https://javafx-jira.kenai.com/browse/RT-39329) – James_D May 19 '15 at 17:37
  • You sir are my Hero. I am unable to vote for this, I just get a Jira login page, that I cannot seem to find a way to Create a User for. I think This question may be closer to what people will be searching for rather than a Curiosity of NamedArg Annotion. is there Anyway to keep it? – bghost4 May 19 '15 at 17:55
  • Bug reporting for JavaFX is migrating in the very near future, so they may not be allowing new registrations at this time. You make a good point that this question is more "searchable" than the linked one, though it was closed while I was typing this comment. The solution may just be to edit the title of the other question to allow better searching there; let me see what I can figure out. – James_D May 19 '15 at 17:57
  • Just for the record, your question is closed as duplicate (because the answer already exists elsewhere on the site), but that doesn't mean it will be removed. Consequently those searching for the same thing will find this question, which will act as a "signpost" to the existing answer. – James_D May 19 '15 at 18:34

0 Answers0