【问题标题】:Draw border around a Canvas在画布周围绘制边框
【发布时间】:2014-11-24 02:58:52
【问题描述】:

我正在编写一个(基本上)模仿 MS Paint 的应用程序;可以选择铅笔工具,用笔画3画一条线;你可以选择Marker工具,画一条笔画为7等的线。

我想在我的画布周围画一个边框。这很简单,是的。但是,对于我拥有的其他方法,我能想到的唯一方法是在绘制边界后进行大量抽查。有没有一种有效的方法来做到这一点,而不会与已选择的工具的笔触/颜色发生冲突?

这里是drawBorder() 方法:

private void drawBorder(GraphicsContext g) {
    final double canvasWidth = g.getCanvas().getWidth();
    final double canvasHeight = g.getCanvas().getHeight();

    g.setStroke(Color.BLACK);
    g.setLineWidth(4);
    g.strokeRect(0, 0, canvasWidth, canvasHeight);

    //sets the color back to the currently selected ColorPicker color
    g.setStroke(selectedColor);
}

但是,此代码会与我的 clear() 操作冲突

clearTool.setOnAction(e -> {
            graphics.clearRect(0, 0,
                canvas.getWidth(), canvas.getHeight());
            drawBorder(graphics);
        });

因为在清除画布后,笔划线宽将为 4。这是一个问题,因为如果我将铅笔工具作为所选工具(笔划线宽为 3),在我选择另一个工具之前它将为 4并切换回铅笔工具;此外,如果我在按下清除按钮时选择了标记工具,同样的概念也适用(在我选择另一个工具然后重新选择标记工具之前,笔划线宽 7 将为 4)。

我试图避免必须为每个工具设置检查,并让它每次都重置笔触的线宽——虽然这样可行,但看起来很复杂。

【问题讨论】:

    标签: java canvas javafx


    【解决方案1】:

    考虑将画布放在窗格中,并使用 CSS 设置窗格的样式。例如:

    import javafx.application.Application;
    import javafx.geometry.Pos;
    import javafx.scene.Scene;
    import javafx.scene.canvas.Canvas;
    import javafx.scene.canvas.GraphicsContext;
    import javafx.scene.control.Button;
    import javafx.scene.layout.Priority;
    import javafx.scene.layout.StackPane;
    import javafx.scene.layout.VBox;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    
    public class CanvasWithBorderExample extends Application {
    
        @Override
        public void start(Stage primaryStage) {
    
            final int SIZE = 400 ;
            Canvas canvas = new Canvas(SIZE, SIZE);
    
            GraphicsContext gc = canvas.getGraphicsContext2D() ;
            gc.setStroke(Color.RED);
            gc.moveTo(0, 0);
            gc.lineTo(SIZE, SIZE);
            gc.stroke();
    
            StackPane canvasContainer = new StackPane(canvas);
            canvasContainer.getStyleClass().add("canvas");
    
            VBox root = new VBox(10, canvasContainer, new Button("Click here"));
            root.setFillWidth(false);
            VBox.setVgrow(canvasContainer, Priority.NEVER);
            root.setAlignment(Pos.CENTER);
    
            Scene scene = new Scene(root);
            scene.getStylesheets().add("canvas-with-border.css");
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    使用 canvas-with-border.css:

    .canvas {
        -fx-background-color: antiquewhite, white ;
        -fx-background-insets: 0, 20 ;
        -fx-padding: 20 ;
    }
    

    【讨论】:

      【解决方案2】:

      编辑:我要快速将 Swing Canvas 知识应用到 JavaFX。如果您在 JavaFX 中使用 resizable Canvas,您仍然需要按照下面的说明进行操作。 如果没有,我可能会使用 Oracle 的 Java tutorial 中描述的分层方法。


      如果我对您的理解正确,那么在我看来您的方法不正确。例如,我假设您在用户绘制铅笔时直接在画布中绘图。这是不正确的。 画布可以随时要求您重新绘制,您必须为此做好准备。

      也就是说,在屏幕外的 GraphicsContext 中进行用户绘图,使用它自己的设置,您可以与用户选择的工具保持一致。 然后,在您的 Canvas paint() 方法中,将该上下文的内容复制到 Canvas。届时您也可以根据需要添加自己的边框或其他注释。

      可能是您已经使用了离屏绘图,并且希望将边框绘制到离屏缓冲区中(例如,由于用户的“添加边框”操作)。然后看看GraphicsContext的save()和restore()方法。它们可以保存状态、更改设置、绘制,然后恢复旧状态。

      【讨论】:

      • 有什么地方可以看到这样的例子吗?
      • JavaFX 中没有Canvas.paint() 方法。
      • @James_D 啊,我的错。改编了答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-28
      • 2015-01-10
      • 2020-10-15
      • 1970-01-01
      相关资源
      最近更新 更多