JavaFX 2.x:如何同时移动线、网格和X轴刻度?

6
以下代码绘制了一个XY折线图:通过左键点击并拖动绘制的线可以向左/右移动。
import javafx.application.Application; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.event.EventHandler;  
import javafx.scene.chart.NumberAxis; 
import javafx.scene.chart.XYChart; 
import javafx.stage.Stage; 
import javafx.scene.Scene; 
import javafx.scene.chart.LineChart; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.BorderPane;
enter code here


public class GridMove extends Application {

    BorderPane pane;
    XYChart.Series series1 = new XYChart.Series();
    SimpleDoubleProperty rectinitX = new SimpleDoubleProperty();
    SimpleDoubleProperty rectX = new SimpleDoubleProperty();
    SimpleDoubleProperty rectY = new SimpleDoubleProperty();

    @Override
    public void start(Stage stage) {

        final NumberAxis xAxis = new NumberAxis(1, 12, 1);
        final NumberAxis yAxis = new NumberAxis(0.53000, 0.53910, 0.0005);

        xAxis.setAnimated(false);
        yAxis.setAnimated(false);

        yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
            @Override
            public String toString(Number object) {
                return String.format("%7.5f", object);
            }
        });

        final LineChart<Number, Number> lineChart = new LineChart<Number, Number>(xAxis, yAxis);

        lineChart.setCreateSymbols(false);
        lineChart.setAlternativeRowFillVisible(false);
        lineChart.setAnimated(false);
        lineChart.setLegendVisible(false);

        series1.getData().add(new XYChart.Data(1, 0.53185));
        series1.getData().add(new XYChart.Data(2, 0.532235));
        series1.getData().add(new XYChart.Data(3, 0.53234));
        series1.getData().add(new XYChart.Data(4, 0.538765));
        series1.getData().add(new XYChart.Data(5, 0.53442));
        series1.getData().add(new XYChart.Data(6, 0.534658));
        series1.getData().add(new XYChart.Data(7, 0.53023));
        series1.getData().add(new XYChart.Data(8, 0.53001));
        series1.getData().add(new XYChart.Data(9, 0.53589));
        series1.getData().add(new XYChart.Data(10, 0.53476));

        pane = new BorderPane();
        pane.setCenter(lineChart);
        Scene scene = new Scene(pane, 800, 600);
        lineChart.getData().addAll(series1);

        stage.setScene(scene);

        scene.setOnMouseClicked(mouseHandler);
        scene.setOnMouseDragged(mouseHandler);
        scene.setOnMouseEntered(mouseHandler);
        scene.setOnMouseExited(mouseHandler);
        scene.setOnMouseMoved(mouseHandler);
        scene.setOnMousePressed(mouseHandler);
        scene.setOnMouseReleased(mouseHandler);
        stage.show();
    }
    EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent mouseEvent) {

            if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) {
                rectinitX.set(mouseEvent.getX());
            } else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED || mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED) {
                LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane.getCenter();
                NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();

                double Tgap = xAxis.getWidth() / (xAxis.getUpperBound() - xAxis.getLowerBound());
                double newXlower = xAxis.getLowerBound(), newXupper = xAxis.getUpperBound();
                double Delta = 0.3;

                if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED) {
                    if (rectinitX.get() < mouseEvent.getX()) {
                        newXlower = xAxis.getLowerBound() - Delta;
                        newXupper = xAxis.getUpperBound() - Delta;
                    } else if (rectinitX.get() > mouseEvent.getX()) {
                        newXlower = xAxis.getLowerBound() + Delta;
                        newXupper = xAxis.getUpperBound() + Delta;
                    }
                    xAxis.setLowerBound(newXlower);
                    xAxis.setUpperBound(newXupper);
                }
                rectinitX.set(mouseEvent.getX());
            }
        }
    };

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

我的问题是:

1)现在通过移动线条左右,网格和X轴刻度不会移动:那么如何同时移动线条、网格和X轴刻度?

2)在JavaFx 2中是否有可能实现这一点?

谢谢。

编辑 没有人愿意帮忙吗?

编辑2: 导入语句已添加

编辑3: 代码改进,现在网格和线条一起移动。只需将X轴刻度与线条和网格一起移动,并且垂直网格线在线条范围值外缺失。

import java.util.Set;
import javafx.application.Application; 
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.collections.ObservableList;
import javafx.event.EventHandler;  
import javafx.scene.chart.Axis;
import javafx.scene.chart.NumberAxis; 
import javafx.scene.chart.XYChart; 
import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage; 
import javafx.scene.Node;
import javafx.scene.Scene; 
import javafx.scene.chart.LineChart; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.BorderPane;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;

public class GridMove extends Application {

BorderPane pane;

XYChart.Series series1 = new XYChart.Series();

SimpleDoubleProperty rectinitX = new SimpleDoubleProperty();
SimpleDoubleProperty rectX = new SimpleDoubleProperty();
SimpleDoubleProperty rectY = new SimpleDoubleProperty();
LineChart<Number, Number> lineChart;

@Override
public void start(Stage stage) {

    final NumberAxis xAxis = new NumberAxis(1, 12, 1);
    final NumberAxis yAxis = new NumberAxis(0.53000, 0.53910, 0.0005);

    xAxis.setAnimated(false);
    yAxis.setAnimated(false);

    yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) {
        @Override
        public String toString(Number object) {
            return String.format("%7.5f", object);
        }
    });

    lineChart = new LineChart<Number, Number>(xAxis, yAxis);

    lineChart.setCreateSymbols(false);
    lineChart.setAlternativeRowFillVisible(false);
    lineChart.setAnimated(false);
    lineChart.setLegendVisible(false);

    series1.getData().add(new XYChart.Data(1, 0.53185));
    series1.getData().add(new XYChart.Data(2, 0.532235));
    series1.getData().add(new XYChart.Data(3, 0.53234));
    series1.getData().add(new XYChart.Data(4, 0.538765));
    series1.getData().add(new XYChart.Data(5, 0.53442));
    series1.getData().add(new XYChart.Data(6, 0.534658));
    series1.getData().add(new XYChart.Data(7, 0.53023));
    series1.getData().add(new XYChart.Data(8, 0.53001));
    series1.getData().add(new XYChart.Data(9, 0.53589));
    series1.getData().add(new XYChart.Data(10, 0.53476));

    pane = new BorderPane();
    pane.setCenter(lineChart);
    Scene scene = new Scene(pane, 800, 600);
    lineChart.getData().addAll(series1);            

    stage.setScene(scene);

    scene.setOnMouseClicked(mouseHandler);
    scene.setOnMouseDragged(mouseHandler);
    scene.setOnMouseEntered(mouseHandler);
    scene.setOnMouseExited(mouseHandler);
    scene.setOnMouseMoved(mouseHandler);
    scene.setOnMousePressed(mouseHandler);
    scene.setOnMouseReleased(mouseHandler);
    stage.show();      
}
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent mouseEvent) {

          if (mouseEvent.getEventType() == MouseEvent.MOUSE_PRESSED) {
            rectinitX.set(mouseEvent.getX());
        } else if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED || mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED) {
            LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane.getCenter();
            NumberAxis xAxis = (NumberAxis) lineChart.getXAxis();

            double newXlower = xAxis.getLowerBound(), newXupper = xAxis.getUpperBound();
            double Delta = 0.3;

            if (mouseEvent.getEventType() == MouseEvent.MOUSE_DRAGGED) {
                if (rectinitX.get() < mouseEvent.getX()) {
                    Delta *= -1;                    
                } 
                newXlower = xAxis.getLowerBound() + Delta;
                newXupper = xAxis.getUpperBound() + Delta;

                xAxis.setLowerBound(newXlower);
                xAxis.setUpperBound(newXupper);

                DoubleProperty p1 = xAxis.scaleXProperty();
                DoubleProperty p2 = xAxis.translateXProperty();

                double horizontalValueRange = xAxis.getUpperBound() - xAxis.getLowerBound();
                double horizontalWidthPixels = xAxis.getWidth();
                //pixels per unit
                double xScale = horizontalWidthPixels / horizontalValueRange;

                Set<Node> nodes = lineChart.lookupAll(".chart-vertical-grid-lines");
                for (Node n: nodes) {
                    Path p = (Path) n;
                    double currLayoutX = p.getLayoutX();
                    p.setLayoutX(currLayoutX + (Delta*-1) * xScale);
                }                    
                double lox = xAxis.getLayoutX();                                      
            }
            rectinitX.set(mouseEvent.getX());
        }
    }
};
public static void main(String[] args) {
    launch(args);
}
}

非常感谢您的帮助!

你具体想要实现什么?当我编译并运行它时(顺便说一下,下次请包含导入,Eclipse/Netbeans很聪明,但不是那么聪明),我看到图表随着刻度标记保持在绘制的点上移动。这很有道理。你是想翻译图表(更改所有点的值)还是想移动图表。你肯定正在按原样移动它。 - Daniel B. Chapman
嗨,丹尼尔:这段代码可以在网格和刻度线保持不动的情况下更改刻度值。此外,由于X轴范围为1到10的整数值,在移动折线图左/右时,不应该有小数。 - Alberto acepsut
有几个问题:首先,当我运行它时,刻度线保持静态,但更改数字以反映您所查看的内容(正确的行为)。其次,如果您关心刻度线的值,需要通过整数值进行设置。现在,您正在使用鼠标事件(double)对其进行设置,从而将其设置为双倍。您需要进行一些计算,以便按(1)的集合“捕捉”它,但这应该不难。如果您想使用刻度线滚动图表,则需要深入了解,因为这似乎不是一个“现成”的解决方案。 - Daniel B. Chapman
嗨,Daniel,感谢您的建议:是的,您直截了当地表达了观点,我的兴趣在于当LineChart向左/右移动时滚动(图表&&刻度线&&网格),这似乎非常棘手:希望能得到一些帮助来解决这个问题。 - Alberto acepsut
我通过子类化轴来解决了它。我提出了一个单独的问题。这是你遇到的同样的问题吗?http://stackoverflow.com/questions/25383566/scrolling-xychart-with-javafx/25397836#25397836 - Adam
显示剩余3条评论
1个回答

0

这其实是一条评论,但我太新了无法发表评论。

我会通过将图表嵌入带有不可见滚动条的ScrollPane中,并将图表的y轴不透明度设置为0来处理此问题。如果无法将所有图表数据加载到内存中,则必须在滚动事件等中管理数据获取。

此外,您还可以使用独立的NumberAxis作为y轴。您需要手动进行适当的缩放和定位。


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