JavaFX奥林匹克五环以正确的顺序重叠
这是我第一次在这里发帖。我目前正在做一项作业,我需要在JavaFX中创建奥运五环,并使它们在正确的位置相交 这就是它应该看起来的样子: 资料来源: 目前,环相交,但它们以我创建对象的顺序占主导地位。蓝色在相交时被黄色覆盖,黄色在相交时被黑色覆盖,等等。正如你在奥运五环图片中看到的,黄色和蓝色第一次相交时,黄色覆盖蓝色,但蓝色第二次覆盖黄色。每个环在相交时都会被另一个环覆盖,但在另一个环上会被覆盖 如果有人能给我指出正确的方向,让它们正确相交,那就太棒了 以下是我目前掌握的代码:JavaFX奥林匹克五环以正确的顺序重叠,java,javafx,Java,Javafx,这是我第一次在这里发帖。我目前正在做一项作业,我需要在JavaFX中创建奥运五环,并使它们在正确的位置相交 这就是它应该看起来的样子: 资料来源: 目前,环相交,但它们以我创建对象的顺序占主导地位。蓝色在相交时被黄色覆盖,黄色在相交时被黑色覆盖,等等。正如你在奥运五环图片中看到的,黄色和蓝色第一次相交时,黄色覆盖蓝色,但蓝色第二次覆盖黄色。每个环在相交时都会被另一个环覆盖,但在另一个环上会被覆盖 如果有人能给我指出正确的方向,让它们正确相交,那就太棒了 以下是我目前掌握的代码: package
package com.company;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class OlympicRings extends Application{
public void start(Stage primaryStage) {
//creates a new object, which will be the first circle
Circle circle1 = new Circle();
circle1.setCenterX(100); //sets the x coordinate for the center of the circle
circle1.setCenterY(100); //sets the y coordinate for the center of the circle
circle1.setRadius(50); //sets the radius of the circle to 50, makes the diameter 100
circle1.setStroke(Color.BLUE); //sets the color of the circle
circle1.setStrokeWidth(10); //sets the thickness of the lines
circle1.setFill(null); //sets the color of the inside of the circle, set to null to enable overlap
Circle circle2 = new Circle(); //creates additional circles
circle2.setCenterX(160);
circle2.setCenterY(150);
circle2.setRadius(50);
circle2.setStroke(Color.YELLOW);
circle2.setStrokeWidth(10);
circle2.setFill(null);
Circle circle3 = new Circle();
circle3.setCenterX(220);
circle3.setCenterY(100);
circle3.setRadius(50);
circle3.setStroke(Color.BLACK);
circle3.setStrokeWidth(10);
circle3.setFill(null);
Circle circle4 = new Circle();
circle4.setCenterX(280);
circle4.setCenterY(150);
circle4.setRadius(50);
circle4.setStroke(Color.GREEN);
circle4.setStrokeWidth(10);
circle4.setFill(null);
Circle circle5 = new Circle();
circle5.setCenterX(340);
circle5.setCenterY(100);
circle5.setRadius(50);
circle5.setStroke(Color.RED);
circle5.setStrokeWidth(10);
circle5.setFill(null);
//creating the pane that will display the circle
Pane pane = new Pane();
pane.getChildren().add(circle1); //each of these adds the various circles to the display of the pane
pane.getChildren().add(circle2);
pane.getChildren().add(circle3);
pane.getChildren().add(circle4);
pane.getChildren().add(circle5);
Scene scene1 = new Scene(pane, 440, 250); //creates the parameters of the pane
primaryStage.setTitle("Olympic Rings"); //names the pane
primaryStage.setScene(scene1); //picks what will go in the pane
primaryStage.show(); //shows the scene i've created
}
}
这很难用圆圈来实现。这将大量使用clip属性,并且生成的代码不容易读取 取而代之的是可以用来画环的一部分。在添加覆盖部分之前,只需将环的覆盖部分添加到母环 前两个环的示例:
private static Arc createArc(double radius,
double centerX, double centerY,
double fromAngle, double toAngle,
Paint stroke,
double strokeWidth) {
Arc arc = new Arc(centerX, centerY, radius, radius, fromAngle, toAngle - fromAngle);
arc.setFill(null);
arc.setStroke(stroke);
arc.setStrokeWidth(strokeWidth);
return arc;
}
@Override
public void start(Stage primaryStage) {
Pane pane = new Pane(
createArc(50, 60, 60, 90, 315, Color.BLUE, 10), // part of the blue ring containing part covered by yellow
createArc(50, 110, 110, 0, 360, Color.YELLOW, 10),
createArc(50, 60, 60, -45, 90, Color.BLUE, 10) // part covering the yellow ring
);
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
谢谢你的提问,我很高兴提出了以下解决方案,请参阅Javadocs了解算法:
package olympicrings;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
/**
* This helper class knows how to paint the next olympic ring into a {@code Pane}.
* It is not limited to 5 olympic rings, it can draw as many (or few) as desired.
* The algorithm it follows is:
* <ol>
* <li>Each ring consists of 2 arcs (half-circles) of the same color, of course.
* Imagine the line connecting the center of the previous ring to the center
* of the current: we place one arc on the LEFT of this line and one arc on
* the RIGHT. Let's call them arcs L and R. These need to be added to the
* children {@code Node}s of the {@code Pane} at the correct order.</li>
* <li>The placement of arc L depends on whether the current ring is at the top
* row or at the bottom:
* <ul>
* <li>TOP: It goes below arc L of the previous ring</li>
* <li>BOTTOM: It goes below arc R of the previous ring</li>
* </ul>
* </li>
* <li>Arc R is always placed last in the list of the children of the {@code Pane}.</li>
* <li>Advance the position of the next ring, taking into account the desired
* ring radius and stroke width.</li>
* </ol>
* <p>
* Usage:
* <pre><code>
* OlympicRingsPaintingContext ctx = new OlympicRingsPaintingContext(thePane, 50, 10);
* ctx.paintNextRing(Color.BLUE);
* ...
* </code></pre>
*/
public class OlympicRingsPaintingContext {
/**
* A handy constant containing the standard olympic colors. Could be used as follows
* to paint the standard olympic rings:
* <pre><code>
* OlympicRingsPaintingContext ctx = new OlympicRingsPaintingContext(thePane, 50, 10);
* OlympicRingsPaintingContext.STANDARD_OLYMPIC_COLORS.forEach(ctx::paintNextRing);
* </code></pre>
*/
public static final List<Color> STANDARD_OLYMPIC_COLORS = Collections.unmodifiableList(Arrays.asList(Color.BLUE, Color.YELLOW, Color.BLACK, Color.GREEN, Color.RED));
private static final double[] TOP_START_ANGLES = new double[] {45, 225};
private static final double[] BOTTOM_START_ANGLES = new double[] {315, 135};
private Pane pane;
private double radius;
private double strokeWidth;
private double curx;
private double cury;
private double topy;
private double bottomy;
private double startAngleL;
private double startAngleR;
private int prevIndexL;
private int prevIndexR;
public OlympicRingsPaintingContext(Pane pane, double radius, double strokeWidth) {
this.pane = pane;
this.radius = radius;
this.strokeWidth = strokeWidth;
topy = 2*radius;
bottomy = 3*radius;
curx = 2*radius;
cury = topy;
startAngleL = TOP_START_ANGLES[0];
startAngleR = TOP_START_ANGLES[1];
prevIndexL = 0;
prevIndexR = 0;
}
public void paintNextRing(Color color) {
addArcL(color);
addArcR(color);
advance();
}
private void addArcL(Color color) {
Arc arcL = makeArc(startAngleL, color);
if( cury == topy ) {
pane.getChildren().add(prevIndexL, arcL);
}
else {
pane.getChildren().add(prevIndexR, arcL);
prevIndexL = prevIndexR;
}
}
private void addArcR(Color color) {
Arc arcR = makeArc(startAngleR, color);
pane.getChildren().add(arcR);
prevIndexR = pane.getChildren().size() - 1;
}
private Arc makeArc(double startAngle, Color color) {
Arc arc = new Arc(curx, cury, radius, radius, startAngle, 180);
arc.setFill(null);
arc.setStroke(color);
arc.setStrokeWidth(strokeWidth);
return arc;
}
private void advance() {
curx += radius + strokeWidth;
if( cury == topy ) {
cury = bottomy;
startAngleL = BOTTOM_START_ANGLES[0];
startAngleR = BOTTOM_START_ANGLES[1];
}
else {
cury = topy;
startAngleL = TOP_START_ANGLES[0];
startAngleR = TOP_START_ANGLES[1];
}
}
}
*/
公共类奥林匹克绘画背景{
/**
*一个包含标准奥运会颜色的方便常数。可按如下方式使用
*要绘制标准的奥运五环:
*
*/
公共静态最终列表标准\u OLYMPIC\u COLORS=Collections.unmodifiableListArrays.asListColor.BLUE、Color.YELLOW、Color.BLACK、Color.GREEN、Color.RED;
私有静态最终双[]顶部开始角度=新双[]{45225};
私有静态最终双[]底_开始_角度=新双[]{315135};
专用窗格;
私人双半径;
私人双冲程宽度;
私人双重宵禁;
私人双槽;
私人双主题;
私人双底;
私人双星;
私人双星;
私人int prevIndexL;
私人int prevIndexR;
public OlympicRingsPaintingContextPane窗格,双半径,双笔划宽度{
this.pane=窗格;
这个半径=半径;
this.strokeWidth=strokeWidth;
topy=2*半径;
底部=3*半径;
curx=2*半径;
cury=topy;
startAngleL=顶部角度[0];
startAngleR=顶角、起始角[1];
prevIndexL=0;
prevIndexR=0;
}
公共空白颜料颜色{
阿达色;
加大色;
进展
}
专用空白添加颜色{
Arc arcL=生成ArcStartAnglel,颜色;
如果cury==topy{
pane.getChildren.addprevIndexL,arcL;
}
否则{
pane.getChildren.addprevIndexR,arcL;
prevIndexL=prevIndexR;
}
}
专用空白添加颜色{
Arc arcR=makeArcstartAngleR,颜色;
pane.getChildren.addarcR;
prevIndexR=pane.getChildren.size-1;
}
私人电弧makeArcdouble startAngle,彩色{
Arc Arc=新的Arccurx,cury,半径,半径,startAngle,180;
arc.setFillnull;
弧度;设置行程颜色;
弧设置行程宽度行程宽度;
返回弧;
}
私人无效预付款{
curx+=半径+冲程宽度;
如果cury==topy{
cury=底部;
startAngleL=底部角度[0];
startAngleR=底部开始角度[1];
}
否则{
cury=topy;
startAngleL=顶部角度[0];
startAngleR=顶角、起始角[1];
}
}
}
用法示例:
我不相信这是可能的使用圆圈单独。也许通过使用一些圆,而不是整个圆,你就能完成这个任务?谢谢!我能找出剩下的弧,这真的很有效。你介意帮我确切地了解顶级构造函数是如何工作的吗?我发现我们创建了一个返回Arc的构造函数,然后在Start类中不断调用该构造函数以利用它。我不知道构造函数正下方的那条线是做什么的,它以Arc=new Arc开头。为什么我们要列出两次半径,为什么我们有一条线是从角度到角度的,而不是绘制笔划?很抱歉,如果这很难理解的话,我正试着把我的头绕到这里。@TomBombadil您可以在这里的javadoc中找到描述:圆弧允许您绘制椭圆形,对于圆的特殊情况,我们有radiusX==radiusY。顺便说一句,createArc不是一个构造函数,它是一个方法。构造函数没有返回类型,只能用于创建包含类的实例。
package olympicrings;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class OlympicRingsApplication extends Application {
public void start(Stage primaryStage) {
Pane pane = new Pane();
OlympicRingsPaintingContext ctx = new OlympicRingsPaintingContext(pane, 50, 10);
OlympicRingsPaintingContext.STANDARD_OLYMPIC_COLORS.forEach(ctx::paintNextRing);
// nobody stops you here though...
// ctx.paintNextRing(javafx.scene.paint.Color.AQUA);
Scene scene1 = new Scene(pane, 440, 250); // creates the parameters of the pane
primaryStage.setTitle("Olympic Rings"); // names the pane
primaryStage.setScene(scene1); // picks what will go in the pane
primaryStage.show(); // shows the scene i've created
}
public static void main(String[] args) {
launch(args);
}
}