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

在JavaFX中使用画布绘制笛卡尔平面图

步博厚
2023-03-14

我有这个方法在JavaFX中使用canvas绘制笛卡尔平面

    public class Grafics extends StackPane {

       private Canvas canvas;

           public void Grafics(){ 

            GridPane grid = new GridPane();
            grid.setPadding(new Insets(5));
            grid.setHgap(10);
            grid.setVgap(10);             

            canvas = new Canvas();
            canvas.setHeight(500);
            canvas.setWidth(700);
            GridPane.setHalignment(canvas, HPos.CENTER);
            grid.add(canvas, 0, 2);

            GraphicsContext gc = canvas.getGraphicsContext2D();
            gc.setFill(Color.BLACK);
            gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
            gc.setFill(Color.WHITE);
            gc.fillRect(1, 1, canvas.getWidth() - 2, canvas.getHeight() - 2);

           drawAxesXY(gc); //call the method drawAxes

           getChildren().addAll(grid);// add an gridpane in stackpane
         }



private void drawAxesXY(GraphicsContext gc1) {

            gc1 = canvas.getGraphicsContext2D().getPixelWriter();  

            PixelWriter pixelWriter = gc1.getPixelWriter();

            gc1.setFill(Color.BLACK);
            gc1.setStroke(Color.BLACK);
            gc1.setLineWidth(1.5);
            gc1.strokeText("Y", 350, 30);
            gc1.scale(1, 1);  
            gc1.translate((canvas.getHeight() / 50) - (canvas.getWidth() / 10), canvas.getHeight() / 50);
           gc1.strokeLine(canvas.getWidth() - 300, canvas.getWidth() - 300, canvas.getHeight() - 100, canvas.getHeight() / 30) ;
           pixelWriter.setColor(300, 300, Color.RED); //use here


           gc1.strokeText("X", 620, 220);  
           gc1.translate(canvas.getWidth() - (canvas.getHeight() / 10), -220);
           gc1.rotate(90.0);
           gc1.setFill(Color.BLACK);
           gc1.setStroke(Color.BLACK);
           gc1.setLineWidth(1.5);
           gc1.strokeLine(canvas.getWidth() - 250, canvas.getWidth() - 250,
                                    canvas.getHeight() - 50, canvas.getHeight() / 30);

           pixelWriter.setColor(620, 220, Color.RED);//use here

                                }
                            }

这是我的密码http://postimg.org/image/uipe1mgyb/的抽屉

我想举一个http://postimg.org/image/98k9mvnb3/例子

在另一篇文章中,他们建议我使用PixelWriter在Canvas中写入像素。我试过了,但它什么也没做。

我认为我在JavaFX中使用画布绘制笛卡尔平面的方法是不正确的,没有其他方法在JavaFX中绘制笛卡尔平面,而不使用PixelWriter。

我如何在JavaFX中用canvas绘制一个笛卡尔平面,并显示axes (x,y) axes和(-x,-y)的坐标,就像示例一样?

共有1个答案

董建德
2023-03-14

我建议使用场景图和内置的NumberAxis节点,而不是使用Canvas编写自己的笛卡尔轴渲染器。

下面的代码并不是一个通用的函数绘图仪,而只是提供了一个说明性示例,说明如何创建一个函数绘图仪。

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;

import java.util.function.Function;

// Java 8 code
public class CartesianPlot extends Application {

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

    @Override
    public void start(final Stage stage) {
        Axes axes = new Axes(
                400, 300,
                -8, 8, 1,
                -6, 6, 1
        );

        Plot plot = new Plot(
                x -> .25 * (x + 4) * (x + 1) * (x - 2),
                -8, 8, 0.1,
                axes
        );

        StackPane layout = new StackPane(
                plot
        );
        layout.setPadding(new Insets(20));
        layout.setStyle("-fx-background-color: rgb(35, 39, 50);");

        stage.setTitle("y = \u00BC(x+4)(x+1)(x-2)");
        stage.setScene(new Scene(layout, Color.rgb(35, 39, 50)));
        stage.show();
    }

    class Axes extends Pane {
        private NumberAxis xAxis;
        private NumberAxis yAxis;

        public Axes(
                int width, int height,
                double xLow, double xHi, double xTickUnit,
                double yLow, double yHi, double yTickUnit
        ) {
            setMinSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);
            setPrefSize(width, height);
            setMaxSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);

            xAxis = new NumberAxis(xLow, xHi, xTickUnit);
            xAxis.setSide(Side.BOTTOM);
            xAxis.setMinorTickVisible(false);
            xAxis.setPrefWidth(width);
            xAxis.setLayoutY(height / 2);

            yAxis = new NumberAxis(yLow, yHi, yTickUnit);
            yAxis.setSide(Side.LEFT);
            yAxis.setMinorTickVisible(false);
            yAxis.setPrefHeight(height);
            yAxis.layoutXProperty().bind(
                Bindings.subtract(
                    (width / 2) + 1,
                    yAxis.widthProperty()
                )
            );

            getChildren().setAll(xAxis, yAxis);
        }

        public NumberAxis getXAxis() {
            return xAxis;
        }

        public NumberAxis getYAxis() {
            return yAxis;
        }
    }

    class Plot extends Pane {
        public Plot(
                Function<Double, Double> f,
                double xMin, double xMax, double xInc,
                Axes axes
        ) {
            Path path = new Path();
            path.setStroke(Color.ORANGE.deriveColor(0, 1, 1, 0.6));
            path.setStrokeWidth(2);

            path.setClip(
                    new Rectangle(
                            0, 0, 
                            axes.getPrefWidth(), 
                            axes.getPrefHeight()
                    )
            );

            double x = xMin;
            double y = f.apply(x);

            path.getElements().add(
                    new MoveTo(
                            mapX(x, axes), mapY(y, axes)
                    )
            );

            x += xInc;
            while (x < xMax) {
                y = f.apply(x);

                path.getElements().add(
                        new LineTo(
                                mapX(x, axes), mapY(y, axes)
                        )
                );

                x += xInc;
            }

            setMinSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);
            setPrefSize(axes.getPrefWidth(), axes.getPrefHeight());
            setMaxSize(Pane.USE_PREF_SIZE, Pane.USE_PREF_SIZE);

            getChildren().setAll(axes, path);
        }

        private double mapX(double x, Axes axes) {
            double tx = axes.getPrefWidth() / 2;
            double sx = axes.getPrefWidth() / 
               (axes.getXAxis().getUpperBound() - 
                axes.getXAxis().getLowerBound());

            return x * sx + tx;
        }

        private double mapY(double y, Axes axes) {
            double ty = axes.getPrefHeight() / 2;
            double sy = axes.getPrefHeight() / 
                (axes.getYAxis().getUpperBound() - 
                 axes.getYAxis().getLowerBound());

            return -y * sy + ty;
        }
    }
}

在对以下问题的回答中提供了此解决方案的一个版本,该版本具有额外的交互式缩放功能:

  • 在JavaFX中创建可缩放坐标系

另一个用户获取了上面的代码,并创建了一个示例,该示例能够绘制用户键入的任意函数。这些函数使用调车场算法进行解析:

    < li >使用调车场算法解析算术表达式并使用javafx绘图 < li >功能绘图仪源。
 类似资料:
  • 问题内容: 在学习了循环,数组,方法之后,…我开始玩图形游戏,但是遇到了一些问题。看到此示例时,我正在寻找一些示例:http : //javaceda.blogspot.ch/2010/06/draw- cartesian-coordinate-system-in.html 它提供了Java中笛卡尔平面的示例。我几乎可以理解该代码的所有内容(除了一些行,例如invokelater,SwingUti

  • 我目前正在使用画布开发一个JavaFX-Drawing-Application。在GraphicsContext的帮助下,我使用beginPath()和lineTo()方法绘制线条,但我无法找到实现橡皮擦的适当方法。

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

  • 本文向大家介绍使用HTML5画布绘制贝塞尔曲线,包括了使用HTML5画布绘制贝塞尔曲线的使用技巧和注意事项,需要的朋友参考一下 是的,请使用HTML canvas方法在HTML5中绘制Bezier曲线。 示例 您可以尝试运行以下代码以使用画布绘制贝塞尔曲线:

  • 我试图创建一个java程序,它将接受来自用户的输入,在网格内绘制一个单个星形(*)矩形。我希望程序接受矩形左上角的(x,y)坐标对,以及矩形的宽度和高度。然后它应该像这个EX一样绘制矩形。(x=16,y=14)和(宽=4,高=5)。我正在努力在哪里接近这一点,因为我试图做到这一点,而不使用数组或二维数组绘制矩形和笛卡尔网格。 我将如何划分绘制20x40网格所需的内聚方法,然后在该网格上绘制一个形状

  • 我正在考虑将我们内部的汽车/测量应用程序从Swing移植到JavaFX,主要是因为它有更好的外观和多点触控支持,但是我找不到一种方法来渲染只有当它们可见时才可以呈现的自定义组件。 为了获得动力,想象一个有10个选项卡的屏幕,每个选项卡内都有一个显示正在测量的一些实时数据的图。任何时候,只能看到一个情节。数据量很大,计算机有足够的能力一次渲染一个情节,但不能同时渲染所有情节。 摇摆版 现在在Swin