首页 文章

JavaFX从画布中删除最后绘制的对象

提问于
浏览
1

介绍:

我创建了一个画布,我的目标是在您在画布上单击的位置创建圆圈 . 但我也希望能够删除我画过的圈子或至少删除最后画出的圈子 . 在圆圈与背景颜色相同的地方重绘不是一个好的解决方案 . 因为如果圆圈下还有其他东西,它们也会被删除 . 例如,在此应用程序中,2个圆圈可能有交叉点,当您尝试删除第2个圆圈时,这些交叉点将为空,这意味着也会删除第一个圆圈的某些部分 . 所以我想到了创建第二个画布 . 每次我在绘制圆圈之前单击画布上的某个地方时,我会将主画布分配给备份画布 . 当我想删除最后绘制的对象时,我可以加载备份画布 .

现在我试着按照我上面解释的那样做,并且无法按照我的意图去做 . 事实上,我甚至在其他事情上看到了一些奇怪的行为(至少对我而言) .

我所做的基本上是创建相同大小的2个画布 .

public class Main extends Application {
    double ldx, ldy, diameter;
    Canvas lastCanvas = new Canvas(800,600);
    Canvas pane1 = new Canvas(800,600);

    @Override
    public void start(Stage primaryStage) throws Exception{
        System.out.println("Hello");
        HBox root = new HBox();

        GraphicsContext gc = pane1.getGraphicsContext2D();
        pane1.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                // Draw circle around x,y
                lastCanvas = pane1;
                diameter = 25.0;
                ldx = event.getSceneX() - ( diameter/2 );
                ldy = event.getSceneY() - ( diameter/2 );
                gc.strokeOval(ldx, ldy, diameter, diameter);
                System.out.println("Clicked");
            }
        });
        VBox pane2 = new VBox(10);
        pane2.setPrefSize(224,600);
        Button button1 = new Button("Clear Last Drawn");
        button1.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                pane1 = lastCanvas;
                System.out.println("Last canvas loaded");
            }
        });
        pane2.getChildren().addAll(button1);
        pane1.setStyle("-fx-background-color: #224488");
        pane2.setStyle("-fx-background-color: #224488");
        root.getChildren().addAll(pane1, pane2);
        Scene scene1 = new Scene(root, 1024, 600);
        primaryStage.setScene(scene1);
        primaryStage.setTitle("Mouse Clicker");
        primaryStage.show();

    }
}

预期的行为是每次我点击按钮它都会在我绘制最后一个对象之前加载lastCanvas作为画布 . 但事实并非如此 . 我在button1的mouseevent中尝试过类似的东西

root.getChildren().removeAll();
root.getChildren().addAll(lastCanvas, pane2);

每次单击按钮时,都会在控制台上生成错误 . 另一个问题是我试图创建第二个场景 .

HBox root2 = new HBox();
root2.getChildren().addAll(lastCanvas, pane2);

尽管我不在任何地方使用root2,但这样做会令人惊讶地删除了pane2上的所有内容 . 我在这里所做的就是创建一个新的HBox并将pane2添加到该hbox中 . 为什么这样做会从我的primaryStage中删除pane2而不是留下空格?

此外,如果您有其他建议删除画布上绘制的最后一个对象-once或直到画布完全为空 - 您还可以告诉我,而不是尝试解决我在上面的代码上做错了 .

3 回答

  • 1

    在不分析问题的情况下,我建议使用您的代码作为基础的以下解决方案

    private final double diameter = 25;
        private final LinkedList<Point2D> centers = new LinkedList<>();
        private final Canvas pane1 = new Canvas(800, 600);
    
        @Override
        public void start(Stage primaryStage) throws Exception
        {
            System.out.println("Hello");
            HBox root = new HBox();
    
            pane1.setOnMouseClicked((MouseEvent event) ->
            {
                centers.add(new Point2D(event.getSceneX(), event.getSceneY()));
                render();
                System.out.println("Clicked");
            });
            VBox pane2 = new VBox(10);
            pane2.setPrefSize(224, 600);
            Button button1 = new Button("Clear Last Drawn");
            button1.setOnMouseClicked((MouseEvent event) ->
            {
                if (!centers.isEmpty())
                {
                    centers.removeLast();
                    render();
                    System.out.println("Last canvas loaded");
                }
            });
            pane2.getChildren().addAll(button1);
            pane1.setStyle("-fx-background-color: #224488");
            pane2.setStyle("-fx-background-color: #224488");
            root.getChildren().addAll(pane1, pane2);
            Scene scene1 = new Scene(root, 1024, 600);
            primaryStage.setScene(scene1);
            primaryStage.setTitle("Mouse Clicker Project (Berk YATKIN)");
            primaryStage.show();
    
        }
    
        private void render()
        {
            pane1.getGraphicsContext2D().clearRect(0, 0, pane1.getWidth(), pane1.getHeight());
            centers.forEach((p) ->
            {
                pane1.getGraphicsContext2D().strokeOval(
                        p.getX() - (diameter / 2),
                        p.getY() - (diameter / 2),
                        diameter,
                        diameter);
            });
        }
    
  • 0

    在没有分析问题的情况下,我首先会问你为什么坚持使用画布 . 场景图更适合这类问题 . 您可以添加(几乎)任意数量的圆圈,并按照您喜欢的顺序删除任意数量的圆圈 . 还有什么比这更容易?

  • 0

    你要求它,所以这里是:

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.Pane;
    import javafx.scene.layout.VBox;
    import javafx.scene.paint.Color;
    import javafx.scene.shape.Circle;
    import javafx.stage.Stage;
    
    public class Main extends Application {
        @Override
        public void start(Stage primaryStage) throws Exception{
            BorderPane root = new BorderPane();
    
            Pane graphicsPane = new Pane();
            root.setCenter(graphicsPane);
    
            graphicsPane.setOnMouseClicked(e -> {
                // Draw circle around x,y
                Circle circle = new Circle(e.getX(), e.getY(), 50.0);
                circle.setStroke(Color.RED);
                circle.setStrokeWidth(4.0);
                circle.setFill(null);
                graphicsPane.getChildren().add(circle);
            });
    
            VBox pane2 = new VBox(10);
            pane2.setPrefWidth(224);
            Button button1 = new Button("Clear Last Drawn");
            button1.setOnAction(e -> {
                int numCircles = graphicsPane.getChildren().size();
                if (numCircles > 0) {
                    graphicsPane.getChildren().remove(numCircles - 1);
                }
            });
    
            pane2.getChildren().addAll(button1);
            root.setRight(pane2);
            graphicsPane.setStyle("-fx-background-color: #aaaaaa");
            pane2.setStyle("-fx-background-color: #224488");
            Scene scene1 = new Scene(root, 1024, 600);
            primaryStage.setScene(scene1);
            primaryStage.setTitle("Mouse Clicker");
            primaryStage.show();
    
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    
    }
    

    这是直接使用场景图的解决方案 . 也可以通过图形选择轻松扩展此示例以移动圆圈或删除圆圈 . 所有用帆布都不容易的东西 .

相关问题