我有这种方法在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中使用画布绘制笛卡尔平面并显示轴(x,y)轴和(-x,-y)的坐标,如示例所示?
答案 0 :(得分:12)
我建议使用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<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;
}
}
}
另一位用户使用上面的代码并使用它创建了一个示例,该示例能够绘制用户输入的任意函数。使用shunting-yard algorithm:
解析函数