当前位置: 首页 > 知识库问答 >
问题:

在画布中绘制,在Gridpane中选择工具

方增
2023-03-14

在附件中,我已经放置了我的项目的图像,实质上我想在画布中绘制不同类型的形状,如线条,圆形,矩形,三角形ecc,当我单击相对按钮时,我是javafx编程的新手,现在我所理解的是,画布只能在GUI的主线程中进行修改,这就是问题所在,因为当我处理按钮事件“SetonAction”时,我需要主画布的参考来绘制线条或循环ecc。我尝试过使用新的线程,但没有成功。如果有人知道一种方法来做到这一点,我真的很满意。感谢建议在这里输入图像描述

对我来说,很难解决这个问题,所以我做了一些简单的代码来理解事情是如何工作的,看看这个:

 public class TE1 extends Application {

private Pane root;
private Pane left;
private StackPane right;
private StackPane drawcontainer;
private CustomizedButton btn;
private CustomizedButton btn1;
private Canvas Drawtable;
private SplitPane divisor;
private double x;
private double y;
private double to_x = 0;
private double to_y = 0;
private int line_no = 1;

@Override
public void start(Stage primaryStage) {
            root = new StackPane();

    Drawtable = new Canvas(400,400);
    Drawtable.setWidth(400);
    Drawtable.setHeight(400);
    GraphicsContext gc = Drawtable.getGraphicsContext2D();
    gc.setFill(Color.CADETBLUE);
    gc.fillRect(0, 0, 800, 850);



    left = new Pane();
    left.setMinSize(400,400);
    left.setStyle("-fx-background-color:#d7d6d5;");
    right= new StackPane();
    right.setAlignment(Pos.CENTER);
   // right.setStyle("-fx-background-color: #FFFFFF;");
    right.setMinSize(400, 400);


    divisor = new SplitPane();


    //root.addEventFilter(DrawEvent.DRAW_TYPE,new DrawEventHandler());
    //root.addEventHandler(DrawEvent.DRAW_TYPE,new DrawEventHandler());
    Drawtable.addEventFilter(DrawEvent.DRAW_TYPE,new DrawEventHandler());
    // right.getChildren().add(Drawtable);

    btn = new CustomizedButton();
    btn1= new CustomizedButton();
    btn.Set_identity("linea");
    btn1.setMinSize(50,50);
    btn.setMinSize(50,50);
    btn.setMaxSize(50, 50);
    btn.setLayoutX(100);
    btn.setLayoutY(100);
    btn1.setLayoutX(100);
    btn1.setLayoutY(180);

    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {

            this.fireEvent();

        }

          public void fireEvent()
         {  
             Runnable task = ()-> runTask();
             Thread background = new Thread(task);
             background.setDaemon(true);
             background.start();




         }


         public void runTask()
         {      


             while(btn.isFocused()){
                 System.out.println("SONO ATTIVO ");
                 Drawtable.setOnMousePressed((event) ->setFromPos(event));
                 System.out.println("x vale :"+x+"y vale: "+y);

                 Drawtable.setOnMouseDragged((event)->
                 {
                     right.getChildren().remove(0);

                     Canvas temp_canvas = new Canvas(400, 400);
                     GraphicsContext gc =  temp_canvas.getGraphicsContext2D();
                      gc.setFill(Color.BLUEVIOLET);
                    // setToPos(event);
                    // drawLine(gc);
                     right.getChildren().add(0,temp_canvas);


                 });

                 Drawtable.setOnMouseReleased((event) -> {
                     final Canvas new_line = new Canvas(400, 400);
                     final GraphicsContext gc = new_line.getGraphicsContext2D();
                     setToPos(event);
                     drawLine(gc);
                    //final new stright line
                    right.getChildren().add(line_no++,new_line);             
                 });

             }

         }






    });




    right.getChildren().addAll( new Canvas(), Drawtable);
    left.getChildren().add(btn);
    left.getChildren().add(btn1);
    divisor.getItems().addAll(left,right);

    root.getChildren().addAll(divisor);



    Scene scene = new Scene(root, 800, 850);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}




/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

 private void setFromPos(MouseEvent event) {
    this.x = event.getX();
    this.y = event.getY();
}
  private void setToPos(MouseEvent event) {
    this.to_x = event.getX();
    this.to_y = event.getY();
}  


private void drawLine(GraphicsContext gc) {
    gc.setFill(Color.RED);
    gc.setStroke(Color.BLACK);
    gc.setLineWidth(1);
    gc.strokeLine(x, y, to_x, to_y);      
     }

  }

谢谢建议

共有2个答案

谷梁波
2023-03-14

我以某种方式成功地修改了代码,如下所示:

   public class TE1 extends Application {

           private Pane root;
           private Pane left;
           private StackPane right;
           private StackPane drawcontainer;
           private CustomizedButton btn;
           private CustomizedButton btn1;
           private Canvas Drawtable;
           private SplitPane divisor;
           private double x;
           private double y;
           private double to_x = 0;
           private double to_y = 0;
           private int line_no = 1;
           private Thread background;

@Override
public void start(Stage primaryStage) {
            root = new StackPane();

    Drawtable = new Canvas(400,400);
    Drawtable.setWidth(400);
    Drawtable.setHeight(400);
    GraphicsContext gc = Drawtable.getGraphicsContext2D();




    left = new Pane();
    left.setMinSize(400,400);
    left.setStyle("-fx-background-color:#d7d6d5;");
    right= new StackPane();
    right.setAlignment(Pos.CENTER);
    right.setStyle("-fx-background-color: #FFFFFF;");
    right.setMinSize(400, 400);


    divisor = new SplitPane();


    btn = new CustomizedButton();
    btn1= new CustomizedButton();
    btn.Set_identity("linea");
    btn1.setMinSize(50,50);
    btn.setMinSize(50,50);
    btn.setMaxSize(50, 50);
    btn.setLayoutX(100);
    btn.setLayoutY(100);
    btn1.setLayoutX(100);
    btn1.setLayoutY(180);

    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {

            this.fireEvent();

        }

          public void fireEvent()
         {  
             Runnable task = ()-> runTask();
             Thread background = new Thread(task);
             background.setDaemon(true);
             background.start();

         }


         public void runTask() 
         {      


             while(btn.isFocused()){
                 System.out.println("SONO ATTIVO ");
                 Drawtable.setOnMousePressed((event) ->setFromPos(event));
                 System.out.println("x vale :"+x+"y vale: "+y);

                 Drawtable.setOnMouseDragged((event)->
                 {

                     right.getChildren().remove(0);

                     Canvas temp_canvas = new Canvas(400, 400);
                     GraphicsContext gc = temp_canvas.getGraphicsContext2D();

                     setToPos(event);
                     drawLine(gc);
                     right.getChildren().add(0,temp_canvas);


                 });

                 Drawtable.setOnMouseReleased((event) -> {
                     final Canvas new_line = new Canvas(400, 400);
                     final GraphicsContext gc = new_line.getGraphicsContext2D();
                     setToPos(event);
                     drawLine(gc);
                    //final new stright line
                    right.getChildren().add(line_no++,new_line);             
                 });

             }
           System.out.println("Focused btn state :"+btn.isFocused());

            background.interrupt();
         }






    });




    right.getChildren().addAll( new Canvas(), Drawtable);
    left.getChildren().add(btn);
    left.getChildren().add(btn1);
    divisor.getItems().addAll(left,right);

    root.getChildren().addAll(divisor);



    Scene scene = new Scene(root, 800, 850);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}




/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

 private void setFromPos(MouseEvent event) {
    this.x = event.getX();
    this.y = event.getY();
}
  private void setToPos(MouseEvent event) {
    this.to_x = event.getX();
    this.to_y = event.getY();
}  


private void drawLine(GraphicsContext gc) {
    gc.setFill(Color.RED);
    gc.setStroke(Color.BLACK);
    gc.setLineWidth(1);
    gc.strokeLine(x, y, to_x, to_y);      
    }

 }

但现在我不明白为什么当按钮没有聚焦时,它不会停止在画布上画线。有什么建议吗??

蔚承天
2023-03-14

这里没有必要使用多线程,也不是一个好主意。

注册事件处理程序不是一个长时间运行的操作,反复使用相同的逻辑重新分配匿名类不会改变任何事情。此外,这些修改需要从JavaFX应用程序线程进行。

另一个应该提到的问题是,在鼠标手势期间,您正在重新创建<code>画布</code>。您应该避免这样做,而是重用现有的画布。还应避免每行堆叠一个画布。如果您需要一个用于当前绘制的线和一个用于完成的线的画布,则为2<code>画布</code>es。顺便说一句,使用s将更容易实现。

我也推荐< code>ToggleButton来完成这种任务。这允许你访问一个独立于焦点的状态。您应该侦听属性,而不是重复查询状态(无论您是使用< code>selected还是< code>focused来添加/移除侦听器):

private Pane root;
private Pane left;
private StackPane right;
private Button btn1;
private Canvas Drawtable;

private Canvas drawingCanvas;
private GraphicsContext drawingContext;

private SplitPane divisor;

@Override
public void start(Stage primaryStage) {
    root = new StackPane();

    Drawtable = new Canvas(400, 400);
    Drawtable.setWidth(400);
    Drawtable.setHeight(400);

    // second Canvas for drawing stacked on top of the other canvas
    drawingCanvas = new Canvas(Drawtable.getWidth(), Drawtable.getHeight());
    drawingContext = drawingCanvas.getGraphicsContext2D();

    left = new Pane();
    left.setMinSize(400, 400);
    left.setStyle("-fx-background-color:#d7d6d5;");
    right = new StackPane(Drawtable, drawingCanvas);
    right.setAlignment(Pos.CENTER);
    right.setStyle("-fx-background-color: #FFFFFF;");
    right.setMinSize(400, 400);

    divisor = new SplitPane();

    ToggleButton btn = new ToggleButton();
    btn1 = new Button();
    btn.setText("linea");
    btn1.setMinSize(50, 50);
    btn.setMinSize(50, 50);
    btn.setMaxSize(50, 50);
    btn.setLayoutX(100);
    btn.setLayoutY(100);
    btn1.setLayoutX(100);
    btn1.setLayoutY(180);

    btn.selectedProperty().addListener(new ChangeListener<Boolean>() {

        private double x;
        private double y;

        private void drawLine(GraphicsContext gc, double endX, double endY) {
            gc.setStroke(Color.BLACK);
            gc.setLineWidth(1);
            gc.strokeLine(x, y, endX, endY);
        }

        private final EventHandler<MouseEvent> pressedHandler = (event) -> {
            x = event.getX();
            y = event.getY();
        };

        private final EventHandler<MouseEvent> draggedHandler = (event) -> {
            // remove old content & draw new content
            drawingContext.clearRect(0, 0, drawingCanvas.getWidth(), drawingCanvas.getHeight());
            drawLine(drawingContext, event.getX(), event.getY());
        };

        private final EventHandler<MouseEvent> releasedHandler = (event) -> {
            // clear canvas for line drawing
            drawingContext.clearRect(0, 0, drawingCanvas.getWidth(), drawingCanvas.getHeight());

            // draw line on background canvas
            final GraphicsContext gc = Drawtable.getGraphicsContext2D();
            drawLine(gc, event.getX(), event.getY());
        };

        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            // add/remove event handlers based on toggle state of the button
            if (newValue) {
                drawingCanvas.addEventHandler(MouseEvent.MOUSE_PRESSED, pressedHandler);
                drawingCanvas.addEventHandler(MouseEvent.MOUSE_DRAGGED, draggedHandler);
                drawingCanvas.addEventHandler(MouseEvent.MOUSE_RELEASED, releasedHandler);
            } else {
                drawingCanvas.removeEventHandler(MouseEvent.MOUSE_PRESSED, pressedHandler);
                drawingCanvas.removeEventHandler(MouseEvent.MOUSE_DRAGGED, draggedHandler);
                drawingCanvas.removeEventHandler(MouseEvent.MOUSE_RELEASED, releasedHandler);
            }
        }

    });

    left.getChildren().add(btn);
    left.getChildren().add(btn1);
    divisor.getItems().addAll(left, right);

    root.getChildren().addAll(divisor);

    Scene scene = new Scene(root, 800, 850);

    primaryStage.setTitle("Hello World!");
    primaryStage.setScene(scene);
    primaryStage.show();
}
 类似资料:
  • 有没有可能通过它们的方程式在画布中画出曲线呢?如果是,怎么做?假设我有一个数学方程y=0,5*x^2,如何打印方程的图形? 我尝试使用和方法,但未成功。

  • 我是Android新手,发现了很多东西。但现在我很沮丧。我想做一个六角形棋盘游戏,用瓷砖。我找到了很多芭蕾舞团,最后决定画出我想要的六边形。 我创建了一个从视图扩展的“Hex”类,添加了一些变量等等。以下是我在主XML布局中的内容: r=大小,x和y是画布上的偏移。以下是我在活动中看到的内容:主活动屏幕 但现在我想选择单十六进制。例如,我想选择左上角的,或右下角的。我在每个视图上都添加了OnCli

  • 我编写了这段代码,可以在JavaFX画布上绘制。它可以很好地工作,但我不知道如何重新绘制画布(比如在Swing中),以便在新画布上重新开始绘制。这是我的代码,非常感谢你的帮助!马里奥

  • 实际上,我可以使用函数来完成。我从“HTML5画布-如何在图像背景上画一条线?”中得到的东西。但是我需要在不使用from函数的情况下绘制图像,如下所示:

  • 我有以下代码应该在图像中绘制线条。我的代码是: 如果我编写,它实际上可以工作。但是我的数组很长并且来自一个输入。