在 JavaFX 中用画布绘制笛卡尔平面图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24005247/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Draw Cartesian Plane Graphi with canvas in JavaFX
提问by DSanches
I have this method to draw the Cartesian plane in JavaFX, using 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
}
}
this is the draw of my codes http://postimg.org/image/uipe1mgyb/
这是我的代码抽奖http://postimg.org/image/uipe1mgyb/
and I want to draw like this examples http://postimg.org/image/98k9mvnb3/
我想画这样的例子http://postimg.org/image/98k9mvnb3/
in another post, they recommended me to use a PixelWriter to write pixels in a Canvas. I tried it, but it doesn't do anything.
在另一篇文章中,他们建议我使用 PixelWriter 在 Canvas 中写入像素。我试过了,但它没有做任何事情。
I think the method I'm using to draw the Cartesian plane using canvas in JavaFX is not correct, do not have another method to draw Cartesian plane in JavaFX, without using PixelWriter.
我认为我在 JavaFX 中使用画布绘制笛卡尔平面的方法是不正确的,没有另一种在 JavaFX 中绘制笛卡尔平面的方法,而不使用 PixelWriter。
How do I draw a Cartesian plane with canvas in JavaFX and show the coordinates of the axes (x, y) axes and (-x,-y), like the example does?
如何在 JavaFX 中使用画布绘制笛卡尔平面并显示轴 (x, y) 轴和 (-x,-y) 的坐标,就像示例一样?
采纳答案by jewelsea
I'd advise using the Scene Graphand the built-in NumberAxisnodes rather than writing your own cartesian axis renderer using a Canvas.
我建议使用Scene Graph和内置的NumberAxis节点,而不是使用Canvas编写自己的笛卡尔轴渲染器。
The code below is not meant to be a general purpose function plotter, but instead just provides an illustrative sample of how you might create one.
下面的代码并不意味着是一个通用的函数绘图仪,而只是提供了一个如何创建一个的说明性示例。
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;
}
}
}
Another user took the code above and created a sample with it that is able to plot arbitrary functions typed in by the user. The functions are parsed using the shunting-yard algorithm:
另一个用户使用上面的代码并用它创建了一个示例,该示例能够绘制用户输入的任意函数。使用调车码算法解析函数: