【问题标题】:Joining points with javaFX使用 javaFX 连接点
【发布时间】:2016-07-08 18:58:56
【问题描述】:

我编写了以下代码,用于通过鼠标事件添加和删除点或圆。下一步是在我创建它们(创建多边形)时用一条线将它们连接起来。我完全卡住了,不知道从哪里开始。我正在寻找文档,但如果有人能指出我正确的方向,我将不胜感激。

package application;

//import all needed classes
import javafx.collections.ObservableList;
import javafx.scene.input.MouseButton;
import javafx.application.Application;
import javafx.scene.shape.Circle;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Node;

public class Main extends Application {

    // using the base class of layout panes
    Pane pane = new Pane();

    @Override
    public void start(Stage primaryStage) {

        // what to do when the mouse is clicked
        pane.setOnMouseClicked(e -> {
            double drawX = e.getX();// position of mouse in X axle
            double drawY = e.getY();// position of mouse in y axle

            if (e.getButton() == MouseButton.PRIMARY) {// get the position of the mouse point when user left click
                Circle circle = makeCircle(drawX, drawY);// using the makeCircle method to draw the circle where the mouse is at the click
                pane.getChildren().add(circle);
            } else if (e.getButton() == MouseButton.SECONDARY) {
                deleteCircle(drawX, drawY);// using the deleteCircle function to delete the circle if right click on the circle
            }

        });

        // container to show all context in a 500px by 500px windows
        try {
            Scene scene = new Scene(pane, 500, 500);// size of the scene
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // method to draw the circle when left click
    private Circle makeCircle(double drawX, double drawY) {
        Circle circle = new Circle(drawX, drawY, 7, Color.CORAL);// create the circle and its properties(color: coral to see it better)
        circle.setStroke(Color.BLACK);// create the stroke so the circle is more visible
        return circle;
    }

    // method to delete the circle using the ObservableList class
    private void deleteCircle(double deletX, double deleteY) {

        // loop to create my list of circles 'til this moment
        ObservableList<Node> list = pane.getChildren();
        for (int i = list.size() - 1; i >= 0; i--) {
            Node circle = list.get(i);

            // checking which circle I want to delete
            if (circle instanceof Circle && circle.contains(deletX, deleteY)) {
                pane.getChildren().remove(circle);
                break;
            }
        }
    }

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

【问题讨论】:

    标签: java javafx


    【解决方案1】:

    我会为窗格的子级添加一个更改侦听器,向窗格添加一个多边形,如果有超过 2 个圆,则重新绘制多边形:

    public class Main extends Application {
    
        // using the base class of layout panes
        Pane pane = new Pane();
        Polygon polygon = new Polygon();
    
        @Override
        public void start(Stage primaryStage) {
    
            // what to do when the mouse is clicked
            pane.setOnMouseClicked(e -> {
                double drawX = e.getX();// position of mouse in X axle
                double drawY = e.getY();// position of mouse in y axle
    
                if (e.getButton() == MouseButton.PRIMARY) {// get the position of the mouse point when user left click
                    Circle circle = makeCircle(drawX, drawY);// using the makeCircle method to draw the circle where the mouse is at the click
                    pane.getChildren().add(circle);
                } else if (e.getButton() == MouseButton.SECONDARY) {
                    deleteCircle(drawX, drawY);// using the deleteCircle function to delete the circle if right click on the circle
                }
    
            });
    
            pane.getChildren().add(polygon);
    
            pane.getChildren().addListener(new ListChangeListener<Node>() {
                @Override
                public void onChanged(Change<? extends Node> c) {
                    int numOfCircles = pane.getChildren().size() - 1;
                    if ( numOfCircles >= 2 ) {
                        polygon.setStroke(Color.BLACK);
                        polygon.getPoints().clear();
                        for ( int i = 0; i <= numOfCircles; i++ ) {
                            Node node = pane.getChildren().get(i);
                            if ( node.getClass() == Circle.class ) {
                                polygon.getPoints().addAll(
                                        ((Circle) node).getCenterX(),
                                        ((Circle) node).getCenterY()
                                );
                            }
                        }
                        System.out.println(polygon.getPoints());
                    }
                }
            });
    
            // container to show all context in a 500px by 500px windows
            try {
                Scene scene = new Scene(pane, 500, 500);// size of the scene
                primaryStage.setScene(scene);
                primaryStage.show();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        // method to draw the circle when left click
        private Circle makeCircle(double drawX, double drawY) {
            Circle circle = new Circle(drawX, drawY, 7, Color.CORAL);// create the circle and its properties(color: coral to see it better)
            circle.setStroke(Color.BLACK);// create the stroke so the circle is more visible
            return circle;
        }
    
        // method to delete the circle using the ObservableList class
        private void deleteCircle(double deletX, double deleteY) {
    
            // loop to create my list of circles 'til this moment
            ObservableList<Node> list = pane.getChildren();
            for (int i = list.size() - 1; i >= 0; i--) {
                Node circle = list.get(i);
    
                // checking which circle I want to delete
                if (circle instanceof Circle && circle.contains(deletX, deleteY)) {
                    pane.getChildren().remove(circle);
                    break;
                }
            }
        }
    
        public static void main(String[] args) {
            Application.launch(args);
        }
    
    }
    

    您也可以不使用更改侦听器,而是在添加或删除圆圈时调用重绘。此外,您还可以为每个调用删除函数的圆圈添加一个 onclick 侦听器,并以更有效的方式删除:

    public class Main extends Application {
    
        // using the base class of layout panes
        Pane pane = new Pane();
        Polygon polygon = new Polygon();
    
        @Override
        public void start(Stage primaryStage) {
    
            // what to do when the mouse is clicked
            pane.setOnMouseClicked(e -> {
                double drawX = e.getX();// position of mouse in X axle
                double drawY = e.getY();// position of mouse in y axle
    
                if (e.getButton() == MouseButton.PRIMARY) {// get the position of the mouse point when user left click
                    Circle circle = makeCircle(drawX, drawY);// using the makeCircle method to draw the circle where the mouse is at the click
                    pane.getChildren().add(circle);
                    circle.setOnMouseClicked( event -> {
                        deleteCircle(circle);
                        // consume event so that the pane on click does not get called
                        event.consume();
                    });
                    redrawPolygon();
                }
    
            });
    
            polygon = new Polygon();
            polygon.setFill(Color.TRANSPARENT);
            polygon.setStroke(Color.BLACK);
            pane.getChildren().add(polygon);
    
            // container to show all context in a 500px by 500px windows
            try {
                Scene scene = new Scene(pane, 500, 500);// size of the scene
                primaryStage.setScene(scene);
                primaryStage.show();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        // method to draw the circle when left click
        private Circle makeCircle(double drawX, double drawY) {
            Circle circle = new Circle(drawX, drawY, 7, Color.CORAL);// create the circle and its properties(color: coral to see it better)
            circle.setStroke(Color.BLACK);// create the stroke so the circle is more visible
            return circle;
        }
    
        private void redrawPolygon() {
            int numOfCircles = pane.getChildren().size() - 1;
            if ( numOfCircles > 0 ) {
                polygon.getPoints().clear();
                for ( int i = 0; i <= numOfCircles; i++ ) {
                    Node node = pane.getChildren().get(i);
                    if ( node.getClass() == Circle.class ) {
                        polygon.getPoints().addAll(
                                ((Circle) node).getCenterX(),
                                ((Circle) node).getCenterY()
                        );
                    }
                }
            }
        }
    
        private void deleteCircle(Circle circle){
            pane.getChildren().remove(circle);
            redrawPolygon();
        }
    
        public static void main(String[] args) {
            Application.launch(args);
        }
    
    }
    

    如果您只想使用一次点击处理程序,您也可以这样做:

       pane.setOnMouseClicked(e -> {
    
            if ( e.getTarget().getClass() == Circle.class ) {
                deleteCircle((Circle)e.getTarget());
            } else {
                Circle circle = makeCircle(e.getX(), e.getY());// using the makeCircle method to draw the circle where the mouse is at the click
                pane.getChildren().add(circle);
                redrawPolygon();
            }
    
        });
    

    【讨论】:

    • 非常感谢!我真的很感谢你的帮助。我今天回家试试看。
    • 效果很好。现在我的下一步是我不希望线条相互交叉。我知道我需要使用算法。有人知道算法的名称和/或如何在我的代码中实现它吗?
    • 堆栈溢出还有其他解决方案。 here is my own though。我正在做的是计算一个中心,然后计算所有点与该中心相比的角度。之后,我按角度排序并使用排序列表绘制多边形。 This is another solution.
    • Here is a picture to explain my solution。红点是我们的多边形点。黑点是我们的中心。黄线是我用来计算黑线角度的基线。黑线是通过中心和多边形点的线。
    • 这可能不是最快/最有效的方法,但它是我能想到的最快的方法:D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-13
    相关资源
    最近更新 更多