如何解决在窗格中显示形状的 ArrayList (JavaFX)
我正在编写一个代码,该代码是一个程序,让用户根据点击位置在屏幕上创建圆圈。我所尝试的是将 create new circle 方法放在第一个事件处理程序中,但它所做的只是给我带来了问题。到目前为止,我正试图以不同的方式解决这个问题。我现在使用 ArrayList 将所有形状组合在一起并将它们显示在窗格上。但是当我运行代码时,圆圈没有显示。
这是我的代码:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.stage.Stage;
import java.util.ArrayList;
public class Main extends Application {
private Pane root;
private Circle circle;
private Line line;
private boolean isClicked = false;
private ArrayList<Circle> circleList;
@Override
public void start(Stage primaryStage) {
root = new Pane();
circle = new Circle();
line = new Line();
circleList = new ArrayList<Circle>();
root.getChildren().addAll(line);
//root.getChildren().addAll(circle); //when this is uncommented the program runs just fine but there is only one circle there at a time
root.getChildren().addAll(circleList); //I feel like the problem Could be here?
root.setonmousepressed(new mouseClick());
root.setonMouseMoved(new moveMouse());
Scene scene = new Scene(root,600,600);
primaryStage.setTitle("blank");
primaryStage.setScene(scene);
primaryStage.show();
}
private double geTradius(double pointOnRadiusX,double pointOnRadiusY,double circleCenterX,double circleCenterY) {
return Math.sqrt(Math.pow(Math.abs(pointOnRadiusX) - Math.abs(circleCenterX),2) + Math.pow(Math.abs(pointOnRadiusY) - Math.abs(circleCenterY),2));
}
private class mouseClick implements EventHandler<MouseEvent> {
@Override
public void handle(MouseEvent e) {
if (!isClicked) {
if(e.getEventType() == MouseEvent.MOUSE_pressed){
circle.seTradius(0);
circle.setCenterX(e.getSceneX());
circle.setCenterY(e.getSceneY());
circle.setstroke(Color.RED);
circle.setFill(Color.TRANSPARENT);
line.setStartX(e.getSceneX());
line.setStartY(e.getSceneY());
line.setstroke(Color.RED);
isClicked = true;
circleList.add(circle);
}
}
else {
circle.seTradius(geTradius(e.getSceneX(),e.getSceneY(),circle.getCenterX(),circle.getCenterY()));
circle.setstroke(Color.GREEN);
line.setstroke(Color.TRANSPARENT);
isClicked = false;
}
}
}
private class moveMouse implements EventHandler <MouseEvent>{
@Override
public void handle(MouseEvent e) {
{
if (isClicked) {
circle.seTradius(geTradius(e.getSceneX(),circle.getCenterY()));
line.setEndX(e.getSceneX());
line.setEndY(e.getSceneY());
}
}
}
}
public static void main(String[] args) {
Application.launch(args);
} }
解决方法
当这段代码被执行时:
root.getChildren().addAll(circleList);
circleList
为空。鉴于您稍后将添加到 circleList
,我将假设您的印象是 addAll
方法以某种方式将两个列表“链接”在一起。它不是。该方法所做的只是复制一个列表中的所有元素并将它们附加到另一个列表中。并注意“复制”我并不是说每个元素都是重复的;添加到一个列表中的元素与给定列表中的实例相同。但列表本身仍然是独立的。
您还必须确保不要将同一个 Circle
实例多次添加到 root
。 Node
最多只能在场景图中出现一次。当添加新圈子的过程开始时,您应该创建一个新的 Circle
对象。如果您打算显示多行,同样适用于您的 Line
。
这是一个工作示例(没有您的 Line
):
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class App extends Application {
private Pane root;
private Circle circle;
@Override
public void start(Stage primaryStage) {
root = new Pane();
root.setOnMousePressed(this::handleMousePressed);
root.setOnMouseMoved(this::handleMouseMoved);
primaryStage.setScene(new Scene(root,1000.0,650.0));
primaryStage.show();
}
private void handleMousePressed(MouseEvent e) {
if (e.getButton() == MouseButton.PRIMARY && e.getClickCount() == 1) {
if (circle == null) {
// start drawing a new circle
circle = new Circle(e.getX(),e.getY(),0.0,Color.TRANSPARENT);
circle.setStroke(Color.RED);
circle.setStrokeWidth(2.0);
root.getChildren().add(circle);
} else {
// "lock" the circle in place
circle.setStroke(Color.GREEN);
circle = null;
}
}
}
private void handleMouseMoved(MouseEvent e) {
// if 'circle' is null then there's no circle being drawn
if (circle != null) {
double x1 = circle.getCenterX();
double y1 = circle.getCenterY();
double x2 = e.getX();
double y2 = e.getY();
double r = Math.sqrt(Math.pow(x2 - x1,2.0) + Math.pow(y2 - y1,2.0));
circle.setRadius(r);
}
}
}
注意我使用私有方法和方法引用来实现鼠标处理程序。这样更简洁,但在行为上与您的内部类相同。
另请注意,我在计算半径时不使用 Math.abs
。使用 abs
实际上是错误的,并且会给你错误的结果 (|x2| - |x1| != x2 - x1
)。例如,如果您有 -3 - 2
会怎样?这给你 |-3| - |2| = 1
,它与 -3 - 2 = -5
不同。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。