我正在尝试绘制多个彼此相邻的图形,其中图形的轴可以位于视口之外。我在嵌套在ScrollPane中的HBox中绘制每个图形。这仅适用于绘制图形的Y轴,但是我想将X轴的标签固定在屏幕上,这样当垂直滚动时,这些标签将始终可见。
我尝试创建一个StackPane,其中嵌套了上面提到的ScrollPane和HBox,第二个HBox嵌套了一个静态层。不幸的是,这破坏了ScrollPane的滚动功能。
有没有办法将标签固定在Y轴上,同时仍可以在X方向上滚动?
当前的FXML:
<VBox>
<ScrollPane>
<HBox>
</HBox>
</ScrollPane>
</VBox>
我尝试过的事情:
<VBox>
<StackPane>
<ScrollPane>
<HBox>
</HBox>
</ScrollPane>
<HBox>
</HBox>
<StackPane>
</VBox>
答案 0 :(得分:0)
我能想到的一种方法是处理ScrollBar而不是ScrollPane。您可以使用轴的上下边界设置scrollBar的最小值/最大值。并在滚动值更改时相应地更新轴范围。像..
final AreaChart chart = new AreaChart(xAxis, yAxis);
ScrollBar scroll = new ScrollBar();
scroll.setMin(chartLowerBound);
scroll.setMax(chartUpperBound);
scroll.setVisibleAmount(10 * tickUnit);
scroll.valueProperty().addListener((obs, old, nxtLb) -> {
double nxtUb = nxtLb.doubleValue() + (10 * tickUnit);
xAxis.setUpperBound(nxtUb);
xAxis.setLowerBound(nxtLb.doubleValue());
});
下面是一个快速工作的示例。尝试了解基本逻辑并根据需要实施。
import java.util.Random;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.ScrollBar;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class ScrollableChartDemo extends Application {
public static void main(String... args) {
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
stage.setTitle("Scrollable Chart");
Random random = new Random(12);
double tickUnit = .04;
double chartLowerBound = 0;
double chartUpperBound = 4;
final ObservableList<Data> seriesData = FXCollections.observableArrayList();
Series series = new Series("Series 1", seriesData);
final ObservableList<Data> series2Data = FXCollections.observableArrayList();
Series series2 = new Series("Series 2", series2Data);
double tempoXAxis = 0.0;
for (int i = 0; i < 100; i++) {
seriesData.add(new Data(tempoXAxis, random.nextInt(12)));
series2Data.add(new Data(tempoXAxis, random.nextInt(12)));
tempoXAxis += tickUnit;
}
final ObservableList<Series> allSeriesData = FXCollections.observableArrayList(series, series2);
NumberAxis xAxis = new NumberAxis("Time", 0, (10 * tickUnit), tickUnit);
NumberAxis yAxis = new NumberAxis();
final AreaChart chart = new AreaChart(xAxis, yAxis);
chart.getData().addAll(allSeriesData);
VBox.setVgrow(chart, Priority.ALWAYS);
ScrollBar scroll = new ScrollBar();
scroll.setMin(chartLowerBound);
scroll.setMax(chartUpperBound - (10 * tickUnit));
scroll.setVisibleAmount(10 * tickUnit);
scroll.valueProperty().addListener((obs, old, nxtLb) -> {
double nxtUb = nxtLb.doubleValue() + (10 * tickUnit);
xAxis.setUpperBound(nxtUb);
xAxis.setLowerBound(nxtLb.doubleValue());
});
chart.setOnScroll((ev) -> {
double nxtUb;
double nxtLb;
if (ev.getDeltaY() > 0) {
nxtUb = xAxis.getUpperBound() + tickUnit;
if (nxtUb > chartUpperBound) {
nxtUb = chartUpperBound;
}
nxtLb = nxtUb - (10 * tickUnit);
} else {
nxtLb = xAxis.getLowerBound() - tickUnit;
if (nxtLb < chartLowerBound) {
nxtLb = chartLowerBound;
}
nxtUb = nxtLb + (10 * tickUnit);
}
xAxis.setUpperBound(nxtUb);
xAxis.setLowerBound(nxtLb);
scroll.setValue(nxtLb);
ev.consume();
});
VBox vb = new VBox();
vb.setSpacing(5);
vb.getChildren().addAll(chart, scroll);
Scene scene = new Scene(vb);
stage.setScene(scene);
stage.setWidth(1000);
stage.setHeight(700);
stage.show();
}
}