属性 在 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();
}
}
这将确保每次布置窗格时只进行一次计算。
在下面的示例中,我在高度和宽度上绑定了一个带有窗格的灰色矩形。蓝色多边形应与矩形成比例。这意味着当我调整 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();
}
}
这将确保每次布置窗格时只进行一次计算。