动态加载指向由FXML构造的多边形

时间:2017-06-07 11:15:07

标签: java dynamic javafx-8 fxml

在这个answer中,一个加载器类用于在构造ComboBox时动态加载它(没有后处理)。
我想使用类似的技术预处理并重用Polygon,但Polygon不会公开items属性或类似的属性。 我的解决方案是扩展Polygon并添加这样的属性:

public class DPolygon extends javafx.scene.shape.Polygon{

    public ObjectProperty<ObservableList<Double>> items =
            new SimpleObjectProperty<>(this, "items");

    public DPolygon() {
        items.addListener(new ChangeListener<ObservableList<Double>>() {
            @Override
            public void changed(ObservableValue<? extends ObservableList<Double>>
            observable, ObservableList<Double> oldValue,
            ObservableList<Double> newValue) {
                addPolyPoints();
            }
        });
    }

    private void addPolyPoints() { super.getPoints().setAll(items.get());}

    public ObjectProperty<ObservableList<Double>>itemsProperty() { return items; }

    public final ObservableList<Double> getItems() {return items.get(); }

    public final void setItems(ObservableList<Double> value) {items.set(value); }
}

有一个装载程序类来提供点数:

public class PointsLoader5 {

    private ObservableList<Double> items;

    public ObservableList<Double> getItems() {

        items = FXCollections.observableArrayList(
                        new Double[] {100.,0.,100., 100., 0., 0.});
        return items;
    }
}

FXML文件中使用两者:

<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.Double?>
<?import javafx.xml_polygon.DPolygon?>

<DPolygon fx:id="triangle" fill="GREEN" stroke="RED" strokeType="INSIDE"
     items="${pointsLoader.items}" xmlns:fx="http://javafx.com/fxml/1" >
</DPolygon>

并将它们放在一起进行测试:

public class DrawTrianle5 extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {

        primaryStage.setTitle("Set points using loader");
        Group group = new Group();
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25, 25, 25, 25));
        group.getChildren().add(grid);

        FXMLLoader loader = new FXMLLoader(getClass().getResource("triangle/Triangle5.fxml"));
        loader.getNamespace().put("pointsLoader", new PointsLoader5());
        DPolygon triangle = loader.load();

        grid.add(triangle, 0, 0);
        Scene scene = new Scene(group, 450, 175);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

没问题 我的问题是:它是正确的方法,还是有更好的方法来动态加载指向由Polygon构造的FXML,避免后处理?

1 个答案:

答案 0 :(得分:1)

阻止您使用当前Polygon类执行此操作的唯一方法是,没有合适的构造函数参数与@NamedArg annotation

所以这样做的一种方法是:

import java.util.List;

import javafx.beans.NamedArg;
import javafx.scene.shape.Polygon;

public class DPolygon extends Polygon {

    public DPolygon(@NamedArg("points") List<Double> points) {
        super(points.stream().mapToDouble(Double::doubleValue).toArray());
    }
}

然后你需要

<DPolygon xmlns:fx="http://javafx.com/fxml/1" points="$points" fill="GREEN" stroke="RED" strokeType="INSIDE" />

测试:

import java.util.Arrays;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;

public class PolygonTest extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("Polygon.fxml"));
        loader.getNamespace().put("points", Arrays.asList(100.0,0.0,100.0,100.0,0.0,0.0));
        Polygon poly = loader.load();
        Scene scene = new Scene(new Group(poly), 450, 175);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

感觉应该有一个没有子类的方法,但我找不到一个有效的方法。