java - 在窗格中显示形状的 ArrayList (JavaFX)
问题描述
我正在编写一个代码,它是一个程序,它让用户根据他们点击的位置在屏幕上创建圆圈。我尝试过的是将创建新圆圈方法放在第一个事件处理程序中,但它所做的只是给我带来了问题。到目前为止,我正试图以不同的方式解决这个问题。我现在使用 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(),e.getSceneY(),circle.getCenterX(), 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
ANode
最多只能在场景图中出现一次。当开始添加新圆圈的过程时,您应该创建一个新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
。
推荐阅读
- reactjs - react-slick:将新项目加载到滑块组件中会导致绝对定位的箭头跳转
- javascript - 使用 NodeJS 将汉字打印到 EPSON TM T88V 的正确方法
- c++ - C++ SymGetLineFromAddr 有错误代码 126
- babeljs - 是否可以进行不包括某些节点类型的 Babel“范围重命名”?
- python - 如何在python中使用硒编辑浏览器元素的html代码
- entity-framework - 如何在 -ignorechanges 迁移后使用新迁移更新我的数据库
- python - 使用 sum 时如何避免出现不支持的类型错误
- karma-runner - 在 Karma 测试环境中使用 Sinon 执行 afterCreate 之前涉及 getRoot 的 Stub MST getter
- python - Django Admin(如果值> x,则显示数据库条目)
- regex - Powershell 正则表达式内容和回写