我正在开发一个需要放大水平条形图(ctrl+鼠标滚轮)的程序,但不是通过放大它,而是通过重新缩放它(只是宽度)。重新缩放是通过更改图表的首选宽度来完成的。这已经很好了,但现在我需要它在光标位置放大......这似乎比我想象的要复杂......我尝试了一些东西,比如尝试设置 scrollpane.hValueProperty,但没有成功。
任何帮助将不胜感激。
下面的代码显示了我的意思......它看起来有点奇怪,因为它只是与 Oracle 教程条形图相结合的更大项目的一部分。
有趣的部分是 Zoomhandler。
import java.util.Arrays;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.collections.FXCollections;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.NumberAxisBuilder;
import javafx.scene.chart.XYChart;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TitledPane;
import javafx.scene.input.ScrollEvent;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
* An advanced horizontal bar chart with a variety of actions and settable
* properties for experimenting with the charts features.
*
* @see javafx.scene.chart.BarChart
* @see javafx.scene.chart.Chart
* @see javafx.scene.chart.NumberAxis
* @see javafx.scene.chart.XYChart
*/
public class BarChartTest extends Application {
ScrollPane scrollPane;
BarChart chart;
private DoubleProperty iniWidth;
private void init(Stage primaryStage) {
scrollPane = new ScrollPane();
Group root = new Group();
primaryStage.setScene(new Scene(scrollPane));
chart = createChart();
root.getChildren().add(chart);
scrollPane.setContent(root);
iniWidth = new SimpleDoubleProperty();
iniWidth.set(100.0d);
scrollPane.addEventFilter(ScrollEvent.ANY, new ZoomHandler());
}
protected BarChart<Number, String> createChart() {
final String[] years = {"2007", "2008", "2009"};
final CategoryAxis yAxis = new CategoryAxis();
final NumberAxis xAxis = NumberAxisBuilder.create()
//.label("ms")
.lowerBound(0.0d)
.autoRanging(false)
.upperBound(3500)
.tickUnit(1000).build();
final BarChart<Number,String> bc = new BarChart<Number,String>(xAxis,yAxis);
// setup chart
bc.setTitle("Horizontal Bar Chart Example");
yAxis.setLabel("Year");
yAxis.setCategories(FXCollections.<String>observableArrayList(Arrays.asList(years)));
xAxis.setLabel("Price");
// add starting data
XYChart.Series<Number,String> series1 = new XYChart.Series<Number,String>();
series1.setName("Data Series 1");
XYChart.Series<Number,String> series2 = new XYChart.Series<Number,String>();
series2.setName("Data Series 2");
XYChart.Series<Number,String> series3 = new XYChart.Series<Number,String>();
series3.setName("Data Series 3");
series1.getData().add(new XYChart.Data<Number,String>(567, years[0]));
series1.getData().add(new XYChart.Data<Number,String>(1292, years[1]));
series1.getData().add(new XYChart.Data<Number,String>(2180, years[2]));
series2.getData().add(new XYChart.Data<Number,String>(956, years[0]));
series2.getData().add(new XYChart.Data<Number,String>(1665, years[1]));
series2.getData().add(new XYChart.Data<Number,String>(2450, years[2]));
series3.getData().add(new XYChart.Data<Number,String>(800, years[0]));
series3.getData().add(new XYChart.Data<Number,String>(1000, years[1]));
series3.getData().add(new XYChart.Data<Number,String>(2800, years[2]));
bc.getData().add(series1);
bc.getData().add(series2);
bc.getData().add(series3);
bc.setMinWidth(100);
bc.setPrefWidth(500);
return bc;
}
@Override public void start(Stage primaryStage) throws Exception {
init(primaryStage);
primaryStage.show();
}
public static void main(String[] args) { launch(args); }
private class ZoomHandler implements EventHandler<ScrollEvent> {
@Override
public void handle(ScrollEvent scrollEvent) {
if (scrollEvent.isControlDown()) {
DoubleProperty x = new SimpleDoubleProperty();
x.set(scrollEvent.getX());
NumberAxis xAxis;
/**
* indicates that tickunit of xAxis needs to be changed
*/
boolean widthChange = false;
/**
* regulates the amount of zooming
*/
double changeWidth = 0;
double newTickUnit = 0;
xAxis = (NumberAxis) chart.getXAxis();
if (scrollEvent.getDeltaY() > 0) {
System.out.println("zoom in");
if (chart.prefWidthProperty().greaterThanOrEqualTo(iniWidth.multiply(2)).get()) {
newTickUnit = xAxis.tickUnitProperty().get()/2;
widthChange = true;
}
changeWidth = 1.1d;
} else {
System.out.println("zoom out");
changeWidth= ((double)10/11);
if (chart.prefWidthProperty().lessThanOrEqualTo(iniWidth).get()) {
newTickUnit= xAxis.tickUnitProperty().get()*2;
widthChange = true;
}
}
if (chart.getPrefWidth()*changeWidth > chart.getMinWidth()) {
Timeline zoomTimeline = new Timeline();
zoomTimeline.getKeyFrames().add(
new KeyFrame(Duration.millis(100), new KeyValue(chart.prefWidthProperty(), chart.getPrefWidth()* changeWidth))
);
zoomTimeline.play();
}
if (widthChange) {
xAxis.tickUnitProperty().set(newTickUnit);
}
if (widthChange) {
if (scrollEvent.getDeltaY() > 0) {
iniWidth.set(iniWidth.multiply(2).get());
} else {
iniWidth.set(iniWidth.divide(2).get());
}
}
}
}
}
}