我的大学教授布置了这个作业,以在课堂上开始一个新主题。只是一个简单的 GUI,应该显示一个图表。我们的教授准备了 3 个文件:
功能画布
package Aufgabe1.jfx;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
final class FunctionCanvas extends Canvas
{
private double c1 = 1, d1 = 0, c2 = 1, d2 = 0;
void setFunctionParameters(double c1, double d1, double c2, double d2)
{
this.c1 = c1;
this.d1 = d1;
this.c2 = c2;
this.d2 = d2;
}
FunctionCanvas() {}
private static final float v = 244f / 255;
private static final Color backGroundColor = Color.color(0, 0, 0);
private static final int yOffset = 20;
void drawFunctionCurve() {
GraphicsContext gc = getGraphicsContext2D();
//float v = 244f / 255;
gc.setFill(backGroundColor);
gc.fillRect(0, 0, getWidth(), getHeight());
double h = this.getHeight() - 2 * yOffset;
int xOffset = 40;
double w = this.getWidth() - 2 * xOffset;
double yZero = yOffset + h / 2;
gc.setFill(Color.BLACK);
gc.fillText("f(x)", xOffset - 30, yOffset);
gc.fillText("0", xOffset - 25, yZero + 5);
gc.fillText("2\u03c0", xOffset + w - 5, yZero - 5);
gc.setLineWidth(1.0);
gc.setStroke(Color.GRAY);
gc.strokeLine(xOffset, yOffset, xOffset, yOffset + h);
gc.strokeLine(xOffset, yZero, xOffset + w, yZero);
gc.setLineWidth(1.5);
gc.setStroke(Color.INDIANRED);
for (int x = 0; x < w; x++) {
int y = (int) ((h / 2) * sinCosFunc(x * 2 * Math.PI / w));
gc.strokeLine(xOffset + x, yZero - y, xOffset + x, yZero - y);
}
}
private double sinCosFunc(double x)
{
return Math.sin(c1 * x + d1) * Math.cos(c2 * x + d2);
}
}
函数曲线
package Aufgabe1.jfx;
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class FunctionCurve extends Application {
public FunctionCurve() { }
@Override
public void start(Stage stage) throws Exception {
int width = 670;
int height = 520;
//Written by me
FXMLLoader loader = new FXMLLoader(getClass().getResource("1gui.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root, width, height);
stage.setTitle(this.getClass().getSimpleName());
stage.setScene(scene);
stage.centerOnScreen();
stage.show();
}
}
主要的
package Aufgabe1.jfx;
final class Main
{
private Main() {}
public static void main(String[] args)
{
javafx.application.Application.launch(FunctionCurve.class, args);
}
}
我已经创建了 FXML 文件并尽我所能编写了控制器:
FXML
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<SplitPane dividerPositions="0.08892617449664429" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" orientation="VERTICAL" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Aufgabe1.jfx.Controller">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<HBox prefHeight="48.0" prefWidth="597.0">
<children>
<Label prefHeight="25.0" prefWidth="25.0" text="c1">
<padding>
<Insets left="5.0" right="5.0" />
</padding>
</Label>
<Spinner editable="true" prefHeight="10.0" prefWidth="50.0" />
<Label prefHeight="25.0" prefWidth="25.0" text="d1">
<padding>
<Insets left="5.0" right="5.0" />
</padding>
</Label>
<Spinner editable="true" prefHeight="10.0" prefWidth="50.0" />
<Label prefHeight="25.0" prefWidth="25.0" text="c2">
<padding>
<Insets left="5.0" right="5.0" />
</padding>
</Label>
<Spinner editable="true" prefHeight="10.0" prefWidth="50.0" />
<Label prefHeight="25.0" prefWidth="25.0" text="d2">
<padding>
<Insets left="5.0" right="5.0" />
</padding>
</Label>
<Spinner editable="true" prefHeight="10.0" prefWidth="50.0" />
<Button mnemonicParsing="false" text="Button">
<HBox.margin>
<Insets left="5.0" right="5.0" />
</HBox.margin>
</Button>
<Button mnemonicParsing="false" text="reset">
<HBox.margin>
<Insets left="5.0" right="5.0" />
</HBox.margin>
</Button>
</children>
</HBox>
</children></AnchorPane>
<AnchorPane fx:id="_canvas" prefHeight="600.0" prefWidth="400.0" />
</items>
</SplitPane>
控制器
package Aufgabe1.jfx;
import javafx.fxml.FXML;
import javafx.scene.layout.AnchorPane;
public class Controller {
@FXML
private AnchorPane _canvas ;
// called by the FXML loader after the labels declared above are injected:
public void initialize() {
FunctionCanvas c = new FunctionCanvas();
_canvas.setPrefWidth(400);
_canvas.setPrefHeight(300);
_canvas.getChildren().add(c);
c.drawFunctionCurve();
}
}
我几乎尝试了在网上遇到的所有解决方案,但是每当我运行应用程序时,带有图表的画布都不会显示。我正在使用 IntelliJ IDEA,如果这可能重要的话......
Canvas
不是一个可调整大小的节点,从javafx.scene.layout
.尤其:
这意味着简单地调整
AnchorPane
包含画布的大小(通过设置其首选宽度和高度)不会对画布的大小产生影响。相反,如上面的文档中所述,您“必须通过在每个实例上设置适当的属性来确定不可调整大小的节点 [画布] 的大小”。画布的“适当属性”就是width
和height
。所以你只需要
顺便说一句,请注意,您基本上可以在 FXML 中完成所有这些操作:无需修改控制器中的场景图。代替
做
(您需要添加
<?import Aufgabe1.jfx.FunctionCanvas?>
到 FXML 前导码),然后在控制器中您需要的是