JavaFX中的带有固定视图y轴的滚动条线形图

3
我正在尝试制作一个可滚动的图表,在滚动条中无论光标位置如何,Y轴都保持在视图中(默认情况下,由于Y轴信息在视图末尾,只有在滚动足够多的情况下才能看到它)。以下是我想要实现的示例:

enter image description here

请注意,即使滚动条位置位于中间,Y轴文本(价格)仍然保持可见。
我在网上搜索了一下,只找到了一个类似的例子,但它似乎不能与scrollPane中的线图一起使用。 在Java FX 2.0中滚动时始终可见的锚定节点? 上面的代码可以使用Circle对象,但更改为Line Chart将导致“异常:无法设置绑定值”,因为在使用scrollpane中的Line chart时似乎会自动调用set layout。
public class FancyScrollPane extends Application {
private LineChart<String, Number> qChart;
@Override
public void start(Stage primaryStage) {
    ScrollPane scrollPane = new ScrollPane();
    Pane content = new Pane();
    final CategoryAxis xAxis = new CategoryAxis();
    final NumberAxis yAxis = new NumberAxis(12, 20, 1);
    yAxis.setSide(Side.RIGHT);
    qChart=new LineChart<String,Number>(xAxis, yAxis);
    qChart.setPrefSize(3000, 250);
    content.getChildren().add(qChart);
    scrollPane.setContent(content);


   Circle immovableObject = new Circle(30, Color.RED);
    content.getChildren().add(immovableObject);

    primaryStage.setScene(new Scene(scrollPane, 300, 300));
    primaryStage.show();

    yAxis.layoutXProperty().bind(
            scrollPane.hvalueProperty()
                .multiply(
                    content.widthProperty()
                        .subtract(
                            new ScrollPaneViewPortWidthBinding(scrollPane))));
}

// we need this class because Bounds object doesn't support binding 
private static class ScrollPaneViewPortWidthBinding extends DoubleBinding {

    private final ScrollPane root;

    public ScrollPaneViewPortWidthBinding(ScrollPane root) {
        this.root = root;
        super.bind(root.viewportBoundsProperty());
    }

    @Override
    protected double computeValue() {
        return root.getViewportBounds().getWidth();
    }
}

public static void main(String[] args) { launch(); }
}

有什么解决上述问题的想法或更好的实现方法吗?谢谢。
1个回答

2

这里有一个小修改,使用setTranslateX方法而不是layoutXProperty来移动y轴和带有滚动条的圆形。

import javafx.application.Application;
import javafx.beans.binding.DoubleBinding;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class FancyScrollPane extends Application {

    @Override
    public void start(Stage primaryStage) {
        ScrollPane scrollPane = new ScrollPane();
        Pane content = new Pane();
        scrollPane.setContent(content);

        // adding background
        content.getChildren().add(new Rectangle(500, 500, Color.GREEN));

        Circle immovableObject = new Circle(30, Color.RED);
        content.getChildren().add(immovableObject);

        primaryStage.setScene(new Scene(scrollPane, 300, 300));
        primaryStage.show();

        immovableObject.layoutXProperty().bind(
                scrollPane.hvalueProperty()
                        .multiply(
                                content.widthProperty()
                                        .subtract(
                                                new ScrollPaneViewPortWidthBinding(scrollPane))));
    }

    // we need this class because Bounds object doesn't support binding
    private static class ScrollPaneViewPortHeightBinding extends DoubleBinding {

        private final ScrollPane root;

        public ScrollPaneViewPortHeightBinding(ScrollPane root) {
            this.root = root;
            super.bind(root.viewportBoundsProperty());
        }

        @Override
        protected double computeValue() {
            return root.getViewportBounds().getHeight();
        }
    }
    // we need this class because Bounds object doesn't support binding
    private static class ScrollPaneViewPortWidthBinding extends DoubleBinding {

        private final ScrollPane root;

        public ScrollPaneViewPortWidthBinding(ScrollPane root) {
            this.root = root;
            super.bind(root.viewportBoundsProperty());
        }

        @Override
        protected double computeValue() {
            return root.getViewportBounds().getWidth();
        }
    }
    public static void main(String[] args) { launch(); }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接