在窗格中显示形状的 ArrayList (JavaFX)

如何解决在窗格中显示形状的 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 实例多次添加到 rootNode 最多只能在场景图中出现一次。当添加新圈子的过程开始时,您应该创建一个新的 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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?