如何使用 SampleController 在 Java FX 中设置轴范围?
How to set Axis range in Java FX using SampleController?
我使用场景生成器 v2.0 创建了一个 fxml 布局。我正在修改控制器文件中的图表,即 SampleController.java 文件。我能够使用 .setTitle 方法设置图表标题。我需要动态设置 xAxis(开始、结束、刻度)和 yAxis 的范围。在 CSS 中,使用 lowerBound 和 upperBound 属性 很容易设置。但这是一个永久的解决方案。请提供您宝贵的建议和解决方案。
Main.java:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.SplitPane;
import javafx.stage.Stage;
public class Main extends Application{
@Override
public void start(Stage primaryStage) {
try {
SplitPane root = (SplitPane)FXMLLoader.load(getClass().getResource("Sample.fxml"));
Scene scene = new Scene(root,800,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<SplitPane dividerPositions="0.7892976588628763" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400.0" minWidth="800.0" prefHeight="400.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<LineChart fx:id="Ch" alternativeColumnFillVisible="true" layoutX="14.0" prefHeight="398.0" prefWidth="500.0">
<xAxis>
<NumberAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis layoutX="10.0" side="LEFT" />
</yAxis>
</LineChart>
</children></AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Button fx:id="sine" layoutX="21.0" layoutY="101.0" mnemonicParsing="false" text="Sinusoidal" />
<Button fx:id="triangle" layoutX="21.0" layoutY="148.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="70.0" text="Triangle" />
<Button fx:id="square" layoutX="21.0" layoutY="187.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="70.0" text="Square" />
<Label layoutX="20.0" layoutY="40.0" prefHeight="17.0" prefWidth="83.0" text="Controls" />
</children></AnchorPane>
</items>
</SplitPane>
SampleController.java
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.Axis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Button;
import javafx.util.Duration;
public class SampleController implements Initializable {
final NumberAxis xAxis = new NumberAxis(0,24,3);
final NumberAxis yAxis = new NumberAxis(0,1,0.1);
@FXML // fx:id="Ch"
private LineChart<Number, Number> Ch= new LineChart<>(xAxis, yAxis); // No use of using a constructor.
@FXML// fx:id="sine"
private Button sine; // Value injected by FXMLLoader
@FXML// fx:id="triangle"
private Button triangle; // Value injected by FXMLLoader
@FXML// fx:id="Square"
private Button square; // Value injected by FXMLLoader
@Override // This method is called by the FXMLLoader when initialization is complete
public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
assert Ch != null : "fx:id=\"Ch\" was not injected: check your FXML file 'sample.fxml'.";
// initialize your logic here: all @FXML variables will have been injected
sine.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Sinusoidal Signal Selected /n/n");
}
});
triangle.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Triangle Signal Selected /n/n");
}
});
square.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Square Signal Selected /n/n");
}
});
//Ch = new LineChart<>(xAxis, yAxis); // This sadly loads a new chart but is not visible
Ch.setTitle("PiScope Demo");
//Need to set xAxis range Dynamically
//Need to set yAxis range Dynamically
/*
* In CSS we can use lowerBound and upperBound Property.
* */
}
}
将轴注入控制器:
<LineChart fx:id="Ch" alternativeColumnFillVisible="true" layoutX="14.0" prefHeight="398.0" prefWidth="500.0">
<xAxis>
<NumberAxis side="BOTTOM" fx:id="xAxis" />
</xAxis>
<yAxis>
<NumberAxis layoutX="10.0" side="LEFT" fx:id="yAxis" />
</yAxis>
</LineChart>
和
public class SampleController implements Initializable {
@FXML
private NumberAxis xAxis ;
@FXML
private NumberAxis yAxis ;
// never initialize fields that are injected by @FXML:
// they are initialized by the FXMLLoader
@FXML // fx:id="Ch"
private LineChart<Number, Number> Ch ;
// ...
}
那么你可以在initialize()
方法中设置范围:
public void initialize() {
// ...
xAxis.setAutoRanging(false);
xAxis.setLowerBound(0);
xAxis.setUpperBound(24);
xAxis.setTickUnit(3);
yAxis.setAutoRanging(false);
yAxis.setLowerBound(0);
yAxis.setUpperBound(1);
yAxis.setTickUnit(0.1);
// ...
}
"axis" 有几种风格与 javafx 图表相关。我发现 fxml 中的 LineChart 初始化导致 Axis。 Axis< T > class 没有 设置上下界的方法。因此,我通过显式转换为 具有这些设置方法的 NumberAxis 找到了解决方案。
public void setAxisBounds(LineChart<Number, Number> myChart, double min, double max, boolean isXAxis) {
NumberAxis axis;
if (isXAxis)
axis=(NumberAxis) myChart.getXAxis();
else
axis=(NumberAxis) myChart.getYAxis();
axis.setAutoRanging(false);
axis.setLowerBound(min);
axis.setUpperBound(max);
}
我使用场景生成器 v2.0 创建了一个 fxml 布局。我正在修改控制器文件中的图表,即 SampleController.java 文件。我能够使用 .setTitle 方法设置图表标题。我需要动态设置 xAxis(开始、结束、刻度)和 yAxis 的范围。在 CSS 中,使用 lowerBound 和 upperBound 属性 很容易设置。但这是一个永久的解决方案。请提供您宝贵的建议和解决方案。
Main.java:
package application;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.SplitPane;
import javafx.stage.Stage;
public class Main extends Application{
@Override
public void start(Stage primaryStage) {
try {
SplitPane root = (SplitPane)FXMLLoader.load(getClass().getResource("Sample.fxml"));
Scene scene = new Scene(root,800,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
Sample.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.chart.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>
<SplitPane dividerPositions="0.7892976588628763" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400.0" minWidth="800.0" prefHeight="400.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController">
<items>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<LineChart fx:id="Ch" alternativeColumnFillVisible="true" layoutX="14.0" prefHeight="398.0" prefWidth="500.0">
<xAxis>
<NumberAxis side="BOTTOM" />
</xAxis>
<yAxis>
<NumberAxis layoutX="10.0" side="LEFT" />
</yAxis>
</LineChart>
</children></AnchorPane>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="100.0">
<children>
<Button fx:id="sine" layoutX="21.0" layoutY="101.0" mnemonicParsing="false" text="Sinusoidal" />
<Button fx:id="triangle" layoutX="21.0" layoutY="148.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="70.0" text="Triangle" />
<Button fx:id="square" layoutX="21.0" layoutY="187.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="70.0" text="Square" />
<Label layoutX="20.0" layoutY="40.0" prefHeight="17.0" prefWidth="83.0" text="Controls" />
</children></AnchorPane>
</items>
</SplitPane>
SampleController.java
package application;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.Axis;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Button;
import javafx.util.Duration;
public class SampleController implements Initializable {
final NumberAxis xAxis = new NumberAxis(0,24,3);
final NumberAxis yAxis = new NumberAxis(0,1,0.1);
@FXML // fx:id="Ch"
private LineChart<Number, Number> Ch= new LineChart<>(xAxis, yAxis); // No use of using a constructor.
@FXML// fx:id="sine"
private Button sine; // Value injected by FXMLLoader
@FXML// fx:id="triangle"
private Button triangle; // Value injected by FXMLLoader
@FXML// fx:id="Square"
private Button square; // Value injected by FXMLLoader
@Override // This method is called by the FXMLLoader when initialization is complete
public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
assert Ch != null : "fx:id=\"Ch\" was not injected: check your FXML file 'sample.fxml'.";
// initialize your logic here: all @FXML variables will have been injected
sine.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Sinusoidal Signal Selected /n/n");
}
});
triangle.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Triangle Signal Selected /n/n");
}
});
square.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Square Signal Selected /n/n");
}
});
//Ch = new LineChart<>(xAxis, yAxis); // This sadly loads a new chart but is not visible
Ch.setTitle("PiScope Demo");
//Need to set xAxis range Dynamically
//Need to set yAxis range Dynamically
/*
* In CSS we can use lowerBound and upperBound Property.
* */
}
}
将轴注入控制器:
<LineChart fx:id="Ch" alternativeColumnFillVisible="true" layoutX="14.0" prefHeight="398.0" prefWidth="500.0">
<xAxis>
<NumberAxis side="BOTTOM" fx:id="xAxis" />
</xAxis>
<yAxis>
<NumberAxis layoutX="10.0" side="LEFT" fx:id="yAxis" />
</yAxis>
</LineChart>
和
public class SampleController implements Initializable {
@FXML
private NumberAxis xAxis ;
@FXML
private NumberAxis yAxis ;
// never initialize fields that are injected by @FXML:
// they are initialized by the FXMLLoader
@FXML // fx:id="Ch"
private LineChart<Number, Number> Ch ;
// ...
}
那么你可以在initialize()
方法中设置范围:
public void initialize() {
// ...
xAxis.setAutoRanging(false);
xAxis.setLowerBound(0);
xAxis.setUpperBound(24);
xAxis.setTickUnit(3);
yAxis.setAutoRanging(false);
yAxis.setLowerBound(0);
yAxis.setUpperBound(1);
yAxis.setTickUnit(0.1);
// ...
}
"axis" 有几种风格与 javafx 图表相关。我发现 fxml 中的 LineChart 初始化导致 Axis
public void setAxisBounds(LineChart<Number, Number> myChart, double min, double max, boolean isXAxis) {
NumberAxis axis;
if (isXAxis)
axis=(NumberAxis) myChart.getXAxis();
else
axis=(NumberAxis) myChart.getYAxis();
axis.setAutoRanging(false);
axis.setLowerBound(min);
axis.setUpperBound(max);
}