【问题标题】:JavaFX - Is it possible to divide a shape into two or more shapes?JavaFX - 是否可以将一个形状分成两个或多个形状?
【发布时间】:2020-04-27 21:43:25
【问题描述】:

例如,我有这个Path

import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;

public class DivideShape extends javafx.application.Application {

    @Override
    public void start(Stage primaryStage) {
        var path = new Path(new MoveTo(200, 380), new LineTo(0, 300),
            new ArcTo(300, 300, 0, 300, 0, false, true), new LineTo(380,
                    200), new ArcTo(180, 180, 0, 200, 380, false, false));
        path.setFill(Color.BLUE);
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(new Scene(new Pane(path)));
        primaryStage.show();
    }

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

而且我想把它分成5份(和分割披萨完全一样)

这可以使用Line 来完成。

但是,这样看起来像 5 个对象,但实际上它仍然是 1 个对象。

是否可以将对象分成5个Paths,这样我就不必一个一个地创建它们了,好吗?

谢谢

更新:

当然,当我修改启动方法时。

@Override
public void start(Stage primaryStage) {
    var pane = new Pane();
    var moveTo = new MoveTo(200, 380);
    var lineTo = new LineTo(0, 300);
    var arc_big = 300;
    var arc_small = 180;
    for (var deg = 198; deg <= 270; deg += 18) {
        var path = new Path(moveTo, lineTo);
        lineTo = new LineTo(300 + arc_big * Math.cos(Math.toRadians(deg)), 300 + arc_big * Math.sin(Math.toRadians(deg)));
        path.getElements().add(new ArcTo(arc_big, arc_big, 0, lineTo.getX(), lineTo.getY(), false, true));
        var move = new MoveTo(380 + arc_small * Math.cos(Math.toRadians(deg)), 380 + arc_small * Math.sin(Math.toRadians(deg)));
        path.getElements().addAll(new LineTo(move.getX(), move.getY()),
        new ArcTo(arc_small, arc_small, 0, moveTo.getX(), moveTo.getY(), false, false));
        moveTo = move;
        path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
        pane.getChildren().add(path);
    }
    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(new Scene(pane));
    primaryStage.show();
}

所以我会创建五个独立的Paths,但是代码太复杂了。这就是为什么我想知道它是否可以划分(1个对象到5个对象),好吗?

【问题讨论】:

    标签: java javafx path shapes


    【解决方案1】:

    当代码变得过于复杂时考虑将其重构为简短的单一职责可重用方法:

    import javafx.application.Application;
    import javafx.geometry.Point2D;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.layout.Pane;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.ArcTo;
    import javafx.scene.shape.LineTo;
    import javafx.scene.shape.MoveTo;
    import javafx.scene.shape.Path;
    import javafx.scene.shape.Shape;
    import javafx.stage.Stage;
    
    public class ConvinienceMethodsExample extends Application {
    
        private static final double OUTER_RADIUS =300, INNER_RADIUS = 180, ORIGIN_X = 300, ORIGIN_Y = 300;
        private static final double START_ANGLE =20, END_ANGLE = 70, STEP_ANGEL = 10;
    
        @Override
        public void start(Stage primaryStage) {
    
            Group group = new Group();
    
            for(double angle =  START_ANGLE; angle < END_ANGLE ; angle += STEP_ANGEL ){
    
                Point2D innerArcStart = getPoint(INNER_RADIUS, angle);
                Point2D innerArcEnd = getPoint(INNER_RADIUS, angle + STEP_ANGEL);
                Point2D outerArcStart = getPoint(OUTER_RADIUS, angle);
                Point2D outerArcEnd = getPoint(OUTER_RADIUS, angle + STEP_ANGEL);
                var path = getPath(innerArcStart, innerArcEnd, outerArcStart, outerArcEnd);
                group.getChildren().add(path);
            }
            primaryStage.setScene(new Scene(new Pane(group)));
            primaryStage.show();
        }
    
        private Point2D getPoint(double radius, double angle){
    
            double x = ORIGIN_X - radius * Math.cos(Math.toRadians(angle));
            double y = ORIGIN_Y - radius * Math.sin(Math.toRadians(angle));
            return new Point2D(x, y);
        }
    
        private Shape getPath(Point2D innerArcStart, Point2D innerArcEnd, Point2D outerArcStart, Point2D outerArcEnd){
            var path = new Path(
                    new MoveTo(innerArcStart.getX(), innerArcStart.getY()),
                    new LineTo(outerArcStart.getX(), outerArcStart.getY()), //left line
                    new ArcTo(OUTER_RADIUS, OUTER_RADIUS, 0, outerArcEnd.getX(), outerArcEnd.getY(), false, true), //outer arc
                    new LineTo(innerArcEnd.getX(),innerArcEnd.getY()), //right line
                    new ArcTo(INNER_RADIUS, INNER_RADIUS, 0, innerArcStart.getX(), innerArcStart.getY(), false, false)
                    );
            path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
            return path;
        }
    
        public static void main(String args[]){
            launch(args);
        }
    } 
    

    【讨论】:

    • 感谢您,抱歉回复晚了。代码很完美,但我太专注于这个形状,以至于忘记了“所有 4 个方向”。但是,这可以通过更改变量轻松解决。 (START_ANGLE = 110/200/290,END_ANGLE = 160/250/340)。但是,仍然存在形状小于问题图像的问题。请问如何调整变量以使大小相同?谢谢
    • 形状的大小由开始和结束角度以及外半径和内半径控制。尝试,例如设置OUTER_RADIUS =400, INNER_RADIUS = 100
    • 不幸的是,它不起作用。与有问题的图像相比,窗口更小,只有形状的内部“侧面”接触到窗口的边缘。但主要的是,内外“边”不是圆形的。
    • 这是两个形状的image。一个在发布的代码中,一个在OUTER_RADIUS =400, INNER_RADIUS = 100, ORIGIN_X = 400, ORIGIN_Y = 400。它确实有效。您需要完全了解代码的作用,才能根据需要对其进行修改。
    • 您好,很抱歉回复晚了。尽管您的代码看起来很简单,比我的简单得多,但我仍然不知道如何获得相同的结果。所以,我很尴尬,但是在那里输入什么值呢?谢谢
    【解决方案2】:

    你可以用 Arc 对象代替 Path 在这段代码中,我制作了五个 18 度的弧,每个弧和一个淡入淡出动画使路径透明。当动画结束时,我从窗格子项中删除路径
    `

     package dividedshape;
    
     import javafx.animation.FadeTransition;
     import javafx.application.Application;
     import javafx.scene.Scene;
     import javafx.scene.layout.Pane;
     import javafx.scene.paint.Color;
     import javafx.scene.shape.*;
     import javafx.stage.Stage;
     import javafx.util.Duration;
    
     public class DivideShape extends Application {
    
    @Override
    public void start(Stage primaryStage) {
      Path path = new Path(new MoveTo(500, 500), new LineTo(0, 500),
                new ArcTo(500, 500, 0, 500, 0, false, true), new LineTo(500, 
        500));
        path.setFill(Color.BLUE);
        Arc arc1 = new Arc(500,500,500,500,90,18);
        arc1.setType(ArcType.ROUND);
        arc1.setFill(Color.BLUE);
        arc1.setStroke(Color.BLACK);
    
        Arc arc2 = new Arc(500,500,500,500,108,18);
        arc2.setType(ArcType.ROUND);
        arc2.setFill(Color.BLUE);
        arc2.setStroke(Color.BLACK);
    
        Arc arc3 = new Arc(500,500,500,500,126,18);
        arc3.setType(ArcType.ROUND);
        arc3.setFill(Color.BLUE);
        arc3.setStroke(Color.BLACK);
    
        Arc arc4 = new Arc(500,500,500,500,144,18);
        arc4.setType(ArcType.ROUND);
        arc4.setFill(Color.BLUE);
        arc4.setStroke(Color.BLACK);
    
        Arc arc5 = new Arc(500,500,500,500,162,18);
        arc5.setType(ArcType.ROUND);
        arc5.setFill(Color.BLUE);
        arc5.setStroke(Color.BLACK);
    
        primaryStage.setTitle("Hello World!");
        Pane pane = new Pane(arc1,arc2,arc3,arc4,arc5,path);
        primaryStage.setScene(new Scene(pane));
        primaryStage.show();
    
        FadeTransition fadePath = new FadeTransition(Duration.seconds(10), path);
        fadePath.setFromValue(10);
        fadePath.setToValue(0);
        fadePath.play();
        fadePath.setOnFinished(e->{ pane.getChildren().remove(path);});
    
    
       }
    
         public static void main(String[] args) {
         launch(args);
         }
        }`
    

    【讨论】:

    • 对不起,我举的例子太简单了。我已经修改过了,现在需要创建 5 个路径。我设法写了它,但是代码太复杂了,所以我根本没有提到它。因此,我想知道是否有相反的过程-不是创建5个对象,而是创建1个对象,我将其分为5个对象。
    • 你可能需要实现一个sin cosin方法
    • 当然我用过,创建了5个独立的对象,但是代码太复杂了。 (请参阅有问题的更新
    猜你喜欢
    • 1970-01-01
    • 2017-01-25
    • 2011-05-18
    • 2017-12-10
    • 2023-03-12
    • 1970-01-01
    • 2021-10-27
    • 2021-07-07
    • 2021-12-13
    相关资源
    最近更新 更多