具有固定视图y轴JavaFX的Scrollpane折线图

时间:2016-06-25 17:10:43

标签: java javafx javafx-8 linechart scrollpane

我正在尝试创建一个可滚动的图表,其中Y轴保持在视图中,无论滚动条中的光标位置如何(默认情况下,因为Y轴信息位于视图的末尾,您只能看到它滚动到足以看到结束后)

这是我想要完成的一个例子:

enter image description here

请注意,即使滚动条位置处于中间位置,Y轴文本(价格)仍然在视图中

我环顾网页,只能找到一个类似的例子,但它似乎不适用于scrollPane中的折线图。

Always visible when scrolled anchored Node in Java FX 2.0?

上述内容适用于Circle对象,但会导致更改为折线图 在“例外:无法设置绑定值”,因为它似乎在滚动窗格内使用折线图时自动调用设置布局

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 个答案:

答案 0 :(得分:1)

这是一个小修改,使用setTranslateX方法而不是layoutXProperty,使用滚动条移动yAxis和圆圈。

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(); }
}