2

我正在开发一个需要放大水平条形图(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());
                    }
                }

            }
        }
    }
}
4

0 回答 0