Ich habe einen Fehler mit der Aktualisierung von Daten auf LineChart bekommen. Nach dem Aktualisieren von LineChart x
Werte nicht gut aktualisiert. Sieht so aus, als ob neue Werte aus der Funktion "gemischt" sind. Nach der Implementierung von Wave packetJavaFX Liniendiagramm wird nicht gut aktualisiert. Datenprobleme
Mit dispersive und ohne es, sollte auf der aktuellen Animation aus Wikipedia rechten Seite der Seite für beide Fälle aussehen. Ich versuche dieses Problem zu finden, was falsch ist, aber ehrlich gesagt kann ich das nicht sehen. Zählen von Daten ist ziemlich sicher in 100% gut. Ich rötete mich irgendwo über diese Art von Problemen, konnte aber mein Problem nicht lösen.
Hauptklasse:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Animation 1D");
primaryStage.setScene(new Scene(root, 1200, 800));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Achsen Klasse:
package sample;
import javafx.scene.chart.NumberAxis;
public class Axes {
private NumberAxis xAxis;
private NumberAxis yAxis;
private double xMin, xMax, yMin, yMax, xTickUnit, yTickUnit;
private int axesWidth, axesHeight;
public Axes() {
this.xMin = 0;
this.xMax = 0;
this.yMin = 0;
this.yMax = 0;
this.xTickUnit = 0;
this.yTickUnit = 0;
this.axesWidth = 0;
this.axesHeight = 0;
}
public NumberAxis getXAxis() {
return xAxis;
}
public NumberAxis getYAxis() {
return yAxis;
}
public int getAxesWidth() {
return axesWidth;
}
public void setAxesWidth(int axesWidth) {
this.axesWidth = axesWidth;
}
public int getAxesHeight() {
return axesHeight;
}
public void setAxesHeight(int axesHeight) {
this.axesHeight = axesHeight;
}
public double getxMin() {
return xMin;
}
public void setxMin(double xMin) {
this.xMin = xMin;
}
public double getxMax() {
return xMax;
}
public void setxMax(double xMax) {
this.xMax = xMax;
}
public double getyMin() {
return yMin;
}
public void setyMin(double yMin) {
this.yMin = yMin;
}
public double getyMax() {
return yMax;
}
public void setyMax(double yMax) {
this.yMax = yMax;
}
public double getxTickUnit() {
return xTickUnit;
}
public void setxTickUnit(double xTickUnit) {
this.xTickUnit = xTickUnit;
}
public double getyTickUnit() {
return yTickUnit;
}
public void setyTickUnit(double yTickUnit) {
this.yTickUnit = yTickUnit;
}
}
Controller-Klasse:
package sample;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.control.ComboBox;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import sample.packet3D.Window3DController;
import java.io.IOException;
public class Controller {
@FXML
private TextField xMin, xMax, yMin, yMax, xTick, yTick, width, height;
@FXML
private NumberAxis xAxis, yAxis;
@FXML
private ComboBox<String> comboBox;
@FXML
private LineChart<Double, Double> axesTest;
@FXML
private Label timeLabel;
private GaussianWave gaussianWave;
private GaussianWaveDispersive gaussianWaveDispersive;
private Axes axes;
private Series<Double, Double> series;
private Timeline timeLine;
@FXML
public void initialize()
{
System.out.println("Initialising...");
axes = new Axes();
yAxis.setAutoRanging(false);
xAxis.setAutoRanging(false);
xMin.setText("-30");
xMax.setText("30");
axesTest.setCreateSymbols(false);
comboBox.getItems().addAll("Gaussian Wave : non-Dispersive", "Gaussian Wave : Dispersive");
//comboBox.getItems().addAll("Gaussian Wave : non-Dispersive");
series = new XYChart.Series<Double, Double>();
timeLine = new Timeline();
applyButtonClicked(null);
}
public void applyButtonClicked(ActionEvent event)
{
System.out.println("Applying new parameters...");
axes.setxMin(Double.parseDouble(xMin.getText()));
axes.setxMax(Double.parseDouble(xMax.getText()));
axes.setyMin(Double.parseDouble(yMin.getText()));
axes.setyMax(Double.parseDouble(yMax.getText()));
axes.setxTickUnit(Double.parseDouble(xTick.getText()));
axes.setyTickUnit(Double.parseDouble(yTick.getText()));
axes.setAxesWidth(Integer.parseInt(width.getText()));
axes.setAxesHeight(Integer.parseInt(height.getText()));
xAxis.setSide(Side.BOTTOM);
xAxis.setMinorTickVisible(false);
xAxis.setPrefWidth(axes.getAxesWidth());
xAxis.setLayoutY(axes.getAxesHeight()/2);
xAxis.autosize();
xAxis.setLowerBound(axes.getxMin());
xAxis.setUpperBound(axes.getxMax());
xAxis.setTickUnit(axes.getxTickUnit());
yAxis.setSide(Side.LEFT);
yAxis.setMinorTickVisible(false);
yAxis.setPrefHeight(axes.getAxesHeight());
yAxis.setLowerBound(axes.getyMin());
yAxis.setUpperBound(axes.getyMax());
yAxis.setTickUnit(axes.getyTickUnit());
}
@FXML
public void startButtonClicked(ActionEvent event)
{
if (comboBox.getValue() == null)
{
System.out.print("Nie wybrano opcji.");
}
else
{
if(comboBox.getValue().equals("Gaussian Wave : non-Dispersive"))
{
System.out.println("Gaussian Wave : non-Dispersive");
axesTest.setTitle("Gaussian Wave : non-Dispersive");
if (series != null)
{
series = new XYChart.Series<Double, Double>();
}
timeLine = new Timeline();
gaussianWave = new GaussianWave(series, axes, timeLine);
series = gaussianWave.draw();
System.out.println("Rozmiar series: "+series.getData().size());
gaussianWave.update(axesTest);
axesTest.getData().add(series);
}
else if(comboBox.getValue().equals("Gaussian Wave : Dispersive"))
{
System.out.println("Gaussian Wave : Dispersive");
axesTest.setTitle("Gaussian Wave : Dispersive");
if (series != null)
{
series = new XYChart.Series<Double, Double>();
}
timeLine = new Timeline();
gaussianWaveDispersive = new GaussianWaveDispersive(series, axes, timeLine);
series = gaussianWaveDispersive.draw();
System.out.println("Rozmiar series: "+series.getData().size());
gaussianWaveDispersive.update(axesTest);
axesTest.getData().add(series);
// axesTest.setTitle("Gaussian Wave : Dispersive");
// gaussianWaveDispersive = new GaussianWaveDispersive(series, axes);
// series = gaussianWaveDispersive.draw();
//
// gaussianWaveDispersive.update(axesTest);
//
// axesTest.getData().add(series);
}
}
}
@FXML
public void restartButtonClicked() {
System.out.println("Restarting...");
timeLine.getKeyFrames().clear();
axesTest.getData().clear();
}
@FXML
public void stopButtonClicked() {
System.out.println("Stopping...");
System.out.println("Restarting...");
timeLine.getKeyFrames().clear();
axesTest.getData().clear();
timeLine.stop();
}
@FXML
public void moveTo3DScene(ActionEvent event) throws IOException {
Stage stage3D = (Stage) ((Node) event.getSource()).getScene().getWindow();
FXMLLoader loader = new FXMLLoader(getClass().getResource("packet3D/Window3DSceneView.fxml"));
Parent root = loader.load();
Window3DController controller = loader.getController();
stage3D.setTitle("Animation 3D");
Scene scene = new Scene(root, 1200, 800, false, SceneAntialiasing.BALANCED);
scene.setOnKeyPressed(e -> controller.onKeyPressed(e));
stage3D.setScene(scene);
stage3D.show();
}
@FXML
public void comboBoxAction() {
}
}
Interfaceklasse:
package sample;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
public interface Countable {
public abstract void methodCounting();
@SuppressWarnings("rawtypes")
public abstract XYChart.Series draw();
public abstract void update(LineChart<Double, Double> lineChart);
}
FXML Klasse über Scene Builder generiert:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.chart.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="borderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="650.0" prefWidth="1025.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<left>
<VBox prefHeight="574.0" prefWidth="270.0" spacing="10.0" BorderPane.alignment="CENTER">
<children>
<GridPane hgap="10.0" vgap="10.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextField promptText="xMin" text="-1" GridPane.columnIndex="1" fx:id="xMin" />
<TextField promptText="xMax" text="1" GridPane.columnIndex="3" fx:id="xMax" />
<TextField fx:id="yMin" promptText="yMin" text="-1" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="yMax" promptText="yMax" text="1" GridPane.columnIndex="3" GridPane.rowIndex="1" />
<TextField fx:id="width" promptText="width" text="1" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<TextField fx:id="height" promptText="height" text="1" GridPane.columnIndex="3" GridPane.rowIndex="3" />
<TextField promptText="xTick" text="0.1" GridPane.columnIndex="1" GridPane.rowIndex="2" fx:id="xTick" />
<TextField fx:id="yTick" promptText="yTick" text="0.1" GridPane.columnIndex="3" GridPane.rowIndex="2" />
<Label text="xMin" />
<Label text="yMin" GridPane.rowIndex="1" />
<Label text="xTick" GridPane.rowIndex="2" />
<Label text="Width" GridPane.rowIndex="3" />
<Label text="Height" GridPane.columnIndex="2" GridPane.rowIndex="3" />
<Label text="yTick" GridPane.columnIndex="2" GridPane.rowIndex="2" />
<Label text="yMax" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<Label text="xMax" GridPane.columnIndex="2" />
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</GridPane>
<Button mnemonicParsing="false" onAction="#applyButtonClicked" prefHeight="25.0" prefWidth="200.0" text="Zatwierdź">
<VBox.margin>
<Insets left="25.0" right="25.0" />
</VBox.margin>
</Button>
<VBox>
<children>
<ComboBox fx:id="comboBox" onAction="#comboBoxAction" prefHeight="25.0" prefWidth="200.0">
<VBox.margin>
<Insets bottom="10.0" left="25.0" right="25.0" top="10.0" />
</VBox.margin>
</ComboBox>
<HBox spacing="10.0">
<children>
<Button fx:id="startButton" mnemonicParsing="false" onAction="#startButtonClicked" prefHeight="25.0" prefWidth="100.0" text="Rozpotrznij">
<HBox.margin>
<Insets />
</HBox.margin>
</Button>
<Button fx:id="restartButton" mnemonicParsing="false" onAction="#restartButtonClicked" prefHeight="25.0" prefWidth="100.0" text="Zatrzymaj" />
</children>
<VBox.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</VBox.margin>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</HBox>
<HBox>
<children>
<Button mnemonicParsing="false" onAction="#stopButtonClicked" prefHeight="25.0" prefWidth="200.0" text="Stop">
<HBox.margin>
<Insets left="25.0" right="25.0" />
</HBox.margin></Button>
</children>
</HBox>
</children>
</VBox>
<Button mnemonicParsing="false" onAction="#moveTo3DScene" prefHeight="25.0" prefWidth="200.0" text="Fala w przestrzeni 3D">
<VBox.margin>
<Insets bottom="10.0" left="25.0" right="25.0" top="10.0" />
</VBox.margin></Button>
<HBox prefHeight="100.0" prefWidth="200.0" />
</children>
<BorderPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</BorderPane.margin>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>
</left>
<center>
<LineChart fx:id="axesTest" prefHeight="500.0" prefWidth="500.0" stylesheets="@style.css" BorderPane.alignment="CENTER">
<xAxis>
<NumberAxis lowerBound="-10.0" side="BOTTOM" fx:id="xAxis" />
</xAxis>
<yAxis>
<NumberAxis fx:id="yAxis" lowerBound="-10.0" side="LEFT" />
</yAxis>
</LineChart>
</center>
<top>
<ToolBar prefHeight="33.0" prefWidth="1025.0" BorderPane.alignment="CENTER">
<items>
<Label alignment="CENTER" text="JavaFX Simulation" textAlignment="CENTER">
<opaqueInsets>
<Insets />
</opaqueInsets>
</Label>
<Region prefHeight="29.0" prefWidth="738.0" />
<Label fx:id="timeLabel" text="Time : " />
</items>
</ToolBar>
</top>
</BorderPane>
2 Logik Klassen zählen Wellen:
package sample;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.util.Duration;
import java.util.function.Function;
public class GaussianWave implements Countable{
private Function<Double, Double> gaussFunction;
private XYChart.Series<Double, Double> series;
private Axes axes;
private Timeline timeline;
private double x;
private double y;
private double xInc;
private double time;
public GaussianWave(XYChart.Series<Double, Double> series, Axes axes, Timeline timeLine) {
this.axes = axes;
//this.series = new XYChart.Series<Number, Number>();
this.series = series;
this.timeline = timeLine;
x = axes.getxMin();
xInc = axes.getxTickUnit();
}
@Override
public void methodCounting() {
double lambda = 1;
this.gaussFunction = x -> Math.sqrt(Math.pow(Math.exp(-(Math.pow((x - this.time), 2)))
* (Math.cos((2 * Math.PI * (x - this.time))/lambda)), 2)
+ Math.pow(Math.exp(-(Math.pow((x - this.time), 2)))
* (Math.sin((2 * Math.PI * (x - this.time))/lambda)), 2));
}
@Override
public Series<Double, Double> draw() {
methodCounting();
while(x < axes.getxMax()) {
y = gaussFunction.apply(x);
series.getData().add(new XYChart.Data<Double, Double>(x , y));
x += xInc;
}
return series;
}
@Override
public void update(LineChart<Double, Double> lineChart) {
System.out.println("Updating");
this.timeline.getKeyFrames().add(
new KeyFrame(Duration.millis(100), e -> {
for (XYChart.Series<Double, Double> series1 : lineChart.getData()) {
for (XYChart.Data<Double, Double> data : series1.getData()) {
Number y = gaussFunction.apply((double)data.getXValue());
data.setYValue((Double) y);
increaseTime();
}
}
})
);
timeline.setCycleCount(1000);
timeline.setAutoReverse(true);
timeline.play();
}
public Function<Double, Double> getGaussFunction() {
return gaussFunction;
}
public void setGaussFunction(Function<Double, Double> gaussFunction) {
this.gaussFunction = gaussFunction;
}
public double getTime() {
return time;
}
public void setTime(double time) {
this.time = time;
}
public void increaseTime(){
this.time += 0.001;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
package sample;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.util.Duration;
import java.util.function.Function;
public class GaussianWaveDispersive implements Countable{
private Function<Double, Double> gaussFunction;
private Series<Double, Double> series;
private Axes axes;
private Timeline timeline;
private double x;
private double y;
private double xInc;
private double time;
public GaussianWaveDispersive(XYChart.Series<Double, Double> series, Axes axes, Timeline timeLine) {
this.axes = axes;
//this.series = new XYChart.Series<Number, Number>();
this.series = series;
this.timeline = timeLine;
x = axes.getxMin();
xInc = axes.getxTickUnit();
}
@Override
public void methodCounting() {
double lambda = 1;
double k = (2 * Math.PI)/lambda;
this.gaussFunction = x -> x = Math.sqrt(Math.pow(1/(Math.pow((1 + Math.pow(4 * time, 2)), (1/4)))
* Math.exp(-((1/Math.pow(1 + (4 * time), 2)) * Math.pow(x - (k * time), 2)))
* Math.cos((1/2) * Math.atan(-(2 * time)) + 1/Math.pow(1 + (4 * time), 2)
* ((k + (2 * time * x)) * x - Math.pow(1/2 * time * k, 2))), 2)
+ Math.pow(1/(Math.pow((1 + Math.pow(4 * time, 2)), (1/4)))
* Math.exp(-((1/Math.pow(1 + (4 * time), 2)) * Math.pow(x - (k * time), 2)))
* Math.sin((1/2) * Math.atan(-(2 * time)) + 1/Math.pow(1 + (4 * time), 2)
* ((k + (2 * time * x)) * x - Math.pow(1/2 * time * k, 2))), 2));
}
@Override
public XYChart.Series<Double, Double> draw() {
methodCounting();
double count = 0;
while(x < axes.getxMax()) {
y = gaussFunction.apply(x);
series.getData().add(new XYChart.Data<Double, Double>(x , y));
x += xInc;
count ++;
System.out.println("Ilosc : " + count + "x : " +x);
}
return series;
}
@Override
public void update(LineChart<Double, Double> lineChart) {
System.out.println("Updating");
this.timeline.getKeyFrames().add(
new KeyFrame(Duration.millis(100), e -> {
for (XYChart.Series<Double, Double> series1 : lineChart.getData()) {
for (XYChart.Data<Double, Double> data : series1.getData()) {
Number y = gaussFunction.apply((double)data.getXValue());
data.setYValue((Double) y);
increaseTime();
}
}
})
);
timeline.setCycleCount(1000);
timeline.setAutoReverse(true);
timeline.play();
}
public Function<Double, Double> getGaussFunction() {
return gaussFunction;
}
public void setGaussFunction(Function<Double, Double> gaussFunction) {
this.gaussFunction = gaussFunction;
}
public double getTime() {
return time;
}
public void setTime(double time) {
this.time = time;
}
public void increaseTime(){
this.time += 0.001;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
Für extrimly hoch für diese Art von equantion x
Werte, die wir dort beobachten können, ist hugh Chaos mit Daten, sollten geht reibungslos wie bei Wikipedia Sample, aber es nicht. Kann mir jemand sagen, wo das Problem ist? Es ist auch sehr schlaff während der Verwendung kleiner x/y
Tick und größer x
und y
Achsen. Was dafür? Vielen Dank im Voraus.
SS zeigt, wie es nach einiger Aktualisierung des Liniendiagramms aussieht.