【问题标题】:Property binding with the points of a polygon in JavaFXJavaFX中多边形点的属性绑定
【发布时间】:2020-12-02 13:51:49
【问题描述】:

在下面的示例中,我将一个灰色矩形与高度和宽度的窗格绑定在一起。蓝色多边形应与矩形成比例。这意味着当我调整窗口大小时,矩形和多边形的边框应该具有相同的大小。

我想我可以使用矩形的 .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();
    }
}

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

【问题讨论】:

  • 只需重新计算每个侦听器中的点。
  • 非常感谢。很高兴知道我在正确的轨道上。

标签: javafx resize polygon points property-binding


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多