在JavaFX中用canvas绘制笛卡尔平面Graphi

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

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中使用canvas绘制笛卡尔平面的方法不正确,没有其他方法在JavaFX中绘制笛卡尔平面,而不使用PixelWriter。

如何在JavaFX中使用canvas绘制笛卡尔平面并显示轴(x,y)轴和(-x,-y)的坐标,如示例所示?

我建议使用Scene Graph和内置的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 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; } } } 

另一个用户使用上面的代码并使用它创建了一个示例,该示例能够绘制用户输入的任意函数。 使用分流码算法解析函数:

  • 使用shunting-yard算法解析算术表达式并使用javafx绘制
  • FunctionPlotter源码 。