属性 在 JavaFX 中绑定多边形的点

Property binding with the points of a polygon in JavaFX

在下面的示例中,我在高度和宽度上绑定了一个带有窗格的灰色矩形。蓝色多边形应与矩形成比例。这意味着当我调整 window.

大小时,矩形和多边形的边界应该具有相同的大小

我想我可以通过矩形的 .addListener 方法(通过 widthProperty 和 heightProperty)来实现。但是我没有成功。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class PolygonFunktion extends Application {

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

    @Override
    public void start(Stage stage) throws Exception {

        Pane pane = new Pane();
        
        //Rectangle
        Rectangle rec = new Rectangle();
        rec.setFill(Color.GRAY);
        
        rec.layoutXProperty().set(20);
        rec.layoutYProperty().set(20);
        rec.widthProperty().bind(pane.widthProperty().subtract(rec.layoutXProperty().multiply(2)));
        rec.heightProperty().bind(pane.heightProperty().subtract(rec.layoutYProperty().multiply(2)));

        //Polygon
        Polygon poly = new Polygon();
        Double[] xy = {0.,0.,  0.,-10., 10.,-10., 10.,-20., 20.,-20., 20.,-30., 30.,-30., 30.,0. };
        poly.getPoints().addAll(xy);
        poly.setFill(Color.BLUE);
        
        poly.layoutXProperty().bind(rec.layoutXProperty());
        poly.layoutYProperty().bind(rec.layoutYProperty().add(rec.heightProperty()));
                
        rec.widthProperty().addListener( (o,oP,nP) -> {
            //... ?
        });
        
        rec.heightProperty().addListener( (o,oP,nP) -> {
            //... ?         
        }); 
        
        pane.getChildren().add(rec);
        pane.getChildren().add(poly);

        stage.setScene(new Scene(pane, 300, 300));
        stage.show();
    }
}

我不想使用缩放方法,因为多边形的边缘也会被缩放。

好的,我有一个可能没有吸引力但有效的解决方案。

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

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class PolygonFunktion extends Application {

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

    @Override
    public void start(Stage stage) throws Exception {

        Pane pane = new Pane();
        
        //Rectangle
        Rectangle rec = new Rectangle();
        rec.setFill(Color.GRAY);
        
        rec.layoutXProperty().set(20);
        rec.layoutYProperty().set(20);
        rec.widthProperty().bind(pane.widthProperty().subtract(rec.layoutXProperty().multiply(2)));
        rec.heightProperty().bind(pane.heightProperty().subtract(rec.layoutYProperty().multiply(2)));

        //Polygon
        Polygon poly = new Polygon();
        Double[] xy = {0.,0.,  0.,-10., 10.,-10., 10.,-20., 20.,-20., 20.,-30., 30.,-30., 30.,0. };
        
        poly.getPoints().addAll(xy);
        poly.setFill(Color.BLUE);
        
        poly.layoutXProperty().bind(rec.layoutXProperty());
        poly.layoutYProperty().bind(rec.layoutYProperty().add(rec.heightProperty()));
        
        
        double maxWidth = poly.getLayoutBounds().getWidth(); 
        double maxHeight =  poly.getLayoutBounds().getHeight();

        
        rec.widthProperty().addListener( (o,oP,nP) -> { 
            
            for(int i=0;  i<poly.getPoints().size(); i+=2) { 
                double polfac = xy[i] / maxWidth;               
                poly.getPoints() .set(i, polfac*nP.doubleValue());
            }  
        });
        
        rec.heightProperty().addListener( (o,oP,nP) -> { 
            
            for(int i=1;  i<poly.getPoints().size(); i+=2) { 
                double polfac = xy[i] / maxHeight;
                poly.getPoints() .set(i, polfac*nP.doubleValue());
            }  
        }); 
        
        pane.getChildren().add(rec);
        pane.getChildren().add(poly);

        stage.setScene(new Scene(pane, 300, 300));
        stage.show();
    }
}

您可以只更新侦听器中的点。请注意,由于每个侦听器都在做同样的事情,因此您只需要一个。类似于:

final int numBars = 3 ;
ChangeListener<Number> recSizeListener = (obs, oldValue, newValue) -> {
    double width = rec.getWidth();
    double height = rec.getHeight();
    Double[] points = new Double[(numBars+1)*4];
    for (int i = 0 ; i <= numBars ; i++) {
        // x values 
        points[i*4] = points[i*4+2] = i*width/numBars ;
        // y values
        points[i*4+1] = -i*height/numBars ;
        points[i*4+3] = -(i+1)*height/numBars ;
    }
    // fix last point:
    points[numBars*4+3] = height ;
    poly.getPoints().setAll(points);
};
rec.widthProperty().addListener(recSizeListener);
rec.heightProperty().addListner(recSizeListener);

然而,与其使用绑定和侦听器,不如在这里使用自定义 Pane 并覆盖 layoutChildren() 方法可能更好:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class PolygonFunktion extends Application {

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

    @Override
    public void start(Stage stage) throws Exception {

        Rectangle rec = new Rectangle();
        rec.setFill(Color.GRAY);
        Polygon poly = new Polygon();
        poly.setFill(Color.BLUE);
        
        final int numBars = 3 ;

        Pane pane = new Pane(rec, poly) {

            final double margin = 20 ;

            @Override
            protected void layoutChildren() {
                double width = getWidth();
                double height = getHeight();
                Double[] points = new Double[(numBars+1)*4];
                rec.setX(margin);
                rec.setY(margin);
                double recWidth = width-2*margin ;
                double recHeight = height-2*margin ;
                rec.setWidth(recWidth);
                rec.setHeight(recHeight);

                for (int bar = 0 ; bar <= numBars ; bar++) {
                    points[4*bar] = points[4*bar+2] = margin + bar*recWidth/numBars ;
                    points[4*bar+1] = recHeight + margin - bar*recHeight/numBars ;
                    points[4*bar+3] = recHeight + margin - (bar+1)*recHeight/numBars ;
                }
                points[4*numBars + 3] = recHeight + margin ;
                
                poly.getPoints().setAll(points);
            }
        };

        stage.setScene(new Scene(pane, 300, 300));
        stage.show();
    }
}

这将确保每次布置窗格时只进行一次计算。