2

在 java 8 中,它声明不推荐使用构建器:http: //mail.openjdk.java.net/pipermail/openjfx-dev/2013-March/006725.html

我正在尝试扩展图表以向图表添加水平和垂直标记。在这种情况下,我正在扩展 LineChart。我希望在开始抛出的 FXML 中使用所述 LineChart:java.lang.NoSuchMethodException: ...chart.LineChartWithMarkers.() 这是由于没有默认构造函数引起的。

由于 Linechart 的构造函数为 XAxis 和 YAxis 使用 2 个参数,因此不推荐使用构建器。我应该如何让 FXML 能够加载我的课程,或者我错过了什么大事?

我真的很想将这一点推广到任何扩展没有默认构造函数的 Node 的类,并使用 Java 8 (8u40+) FXML 库。我还没有找到一个明确的答案。我所听到的只是构建器在 JDK9 中被完全弃用和删除,但如果您在 FXML 中使用它,则没有解决方案取代它们或需要覆盖什么方法才能使其工作。

据我所知,在添加任何必填字段之前,构建者不会创建类的实例。

希望有人会插话并告诉我我错过了什么。

自定义图表的 Java 类

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);
    }


}

和 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>
4

0 回答 0