2

此代码在下窗格中绘制 LineChart 上窗格和条形图。

还有一条用指针向左/向右 X 移动的垂直线。

我想将这条垂直线也延伸到下部子窗格,如附图

在此处输入图像描述

如何做到这一点?

谢谢。

这是代码

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.control.SplitPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.LineBuilder;
import javafx.stage.Stage;

public class XyChartInSplitOnlyCursor extends Application {
SplitPane               splitPane1 = null; 
BorderPane              pane1; 
BorderPane              pane2; 
Line                    LV;
XYChart.Series          series1 = new XYChart.Series(); 
XYChart.Series          series2 = new XYChart.Series(); 

@Override 
public void start(Stage stage) {      
stage.setTitle("Lines plot"); 

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

xAxis.setAnimated(false);
xAxis.setScaleX(0);
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> lineChart1 = new LineChart<Number, Number>(xAxis, yAxis); 

lineChart1.setCreateSymbols(false); 
lineChart1.setAlternativeRowFillVisible(false); 
lineChart1.setAnimated(false); 
lineChart1.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)); 
series1.getData().add(new XYChart.Data(11, 0.530123)); 
series1.getData().add(new XYChart.Data(12, 0.531035)); 

lineChart1.getData().addAll(series1);         

pane1 = new BorderPane(); 
pane1.setCenter(lineChart1); 

splitPane1 = new SplitPane();                                
splitPane1.setOrientation(Orientation.VERTICAL);
splitPane1.getItems().addAll(pane1);
splitPane1.setDividerPosition(0, 1);

final CategoryAxis xAxis2 = new CategoryAxis();
final NumberAxis   yAxis2 = new NumberAxis();

yAxis2.setTickUnit(1);
yAxis2.setPrefWidth(35);
yAxis2.setMinorTickCount(10);

yAxis2.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis2){
        @Override
        public String toString(Number object){
            String label;
            label = String.format("%7.2f", object.floatValue());
            return label;
        }
});

final BarChart<String, Number>BarChart = new BarChart<String, Number>(xAxis2, yAxis2);

BarChart.setAlternativeRowFillVisible(false);
BarChart.setLegendVisible(false);
BarChart.setAnimated(false);

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

series2.getData().add(new XYChart.Data("Jan", 1));
series2.getData().add(new XYChart.Data("Feb", 3));
series2.getData().add(new XYChart.Data("Mar", 1.5));
series2.getData().add(new XYChart.Data("Apr", 3));
series2.getData().add(new XYChart.Data("May", 4.5));
series2.getData().add(new XYChart.Data("Jun", 5));
series2.getData().add(new XYChart.Data("Jul", 4));
series2.getData().add(new XYChart.Data("Aug", 8));
series2.getData().add(new XYChart.Data("Sep", 16.5));
series2.getData().add(new XYChart.Data("Oct", 13.9));
series2.getData().add(new XYChart.Data("Nov", 17));
series2.getData().add(new XYChart.Data("Dec", 20));

BarChart.getData().addAll(series2);

pane2 = new BorderPane(); 
pane2.setCenter(BarChart);

Platform.runLater(new Runnable() {
     @Override
     public void run() {
         double percSplit;

         splitPane1.getItems().addAll(pane2);

        ObservableList<SplitPane.Divider> splitDiv =  splitPane1.getDividers();

        percSplit = 1/(double)(splitDiv.size()+1);
        for (int i = 0; i< splitDiv.size(); i++) {                        
            splitPane1.setDividerPosition(i, percSplit);
            percSplit += 1/(double)(splitDiv.size()+1);
            }
     }
 });

Scene scene = new Scene(splitPane1, 800, 600); 
stage.setScene(scene);         

pane1.setOnMouseMoved(mouseHandler); 

LV=LineBuilder.create()
        .startX(0)
        .startY(0)
        .endX(10)
        .endY(.535)
        .strokeWidth(1)
        .stroke(Color.BLACK)
        .build();
pane1.getChildren().add(LV);

stage.show();
} 
EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() { 

@Override 
public void handle(MouseEvent mouseEvent) {
    if (mouseEvent.getEventType() == MouseEvent.MOUSE_MOVED) { 
        LineChart<Number, Number> lineChart = (LineChart<Number, Number>) pane1.getCenter(); 

        NumberAxis yAxis = (NumberAxis) lineChart.getYAxis(); 
        NumberAxis xAxis = (NumberAxis) lineChart.getXAxis(); 

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

        double xAxisShift = getSceneShift(xAxis);
        double yAxisShift = getSceneShift(yAxis);

        if(mouseEvent.getX()>xAxisShift && mouseEvent.getX()<xAxisShift+xAxis.getWidth()){

        LV.setStartX(mouseEvent.getX());
        LV.setStartY(yAxisShift);
        LV.setEndX(mouseEvent.getX());
        LV.setEndY(yAxisShift+yAxis.getHeight());
        }
    } 
}
}; 
private static double getSceneShift(Node node) { 
double shift = 0; 
do {  
    shift += node.getLayoutX();  
    node = node.getParent(); 
} while (node != null); 
return shift; 
}   
public static void main(String[] args) { 
launch(args);  
} 
}

编辑:jewelsea修改后添加图片

在此处输入图像描述

4

1 回答 1

3

不要将线添加到 SplitPane 中的窗格,而是创建一个组,将线分层在 SplitPane 上。

Scene scene = new Scene(new Group(splitPane1, line), 800, 600); 

如果您希望场景可调整大小,您可以使用 StackPane 而不是 Group 并将线条长度绑定到场景高度以使其填充场景。

这是使用 StackPane 和绑定以在可调整大小的场景中扩展线条的示例。请注意,与最初发布的代码类似,该代码被明确编码为仅当鼠标位于顶部图表的绘图区域内时才移动线条。

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Orientation;
import javafx.scene.*;
import javafx.scene.chart.*;
import javafx.scene.control.SplitPane;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.LineBuilder;
import javafx.stage.Stage;

public class XyChartInSplitOnlyCursor extends Application {
  SplitPane splitPane1 = null;
  BorderPane pane1;
  BorderPane pane2;
  Line LV1, LV2;
  XYChart.Series series1 = new XYChart.Series();
  XYChart.Series series2 = new XYChart.Series();

  @Override
  public void start(Stage stage) {
    stage.setTitle("Lines plot");

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

    xAxis.setAnimated(false);
    xAxis.setScaleX(0);
    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> lineChart1 = new LineChart<Number, Number>(xAxis, yAxis);

    lineChart1.setCreateSymbols(false);
    lineChart1.setAlternativeRowFillVisible(false);
    lineChart1.setAnimated(false);
    lineChart1.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));
    series1.getData().add(new XYChart.Data(11, 0.530123));
    series1.getData().add(new XYChart.Data(12, 0.531035));

    lineChart1.getData().addAll(series1);

    pane1 = new BorderPane();
    pane1.setCenter(lineChart1);

    splitPane1 = new SplitPane();
    splitPane1.setOrientation(Orientation.VERTICAL);
    splitPane1.getItems().addAll(pane1);
    splitPane1.setDividerPosition(0, 1);

    final CategoryAxis xAxis2 = new CategoryAxis();
    final NumberAxis yAxis2 = new NumberAxis();

    yAxis2.setTickUnit(1);
    yAxis2.setPrefWidth(35);
    yAxis2.setMinorTickCount(10);

    yAxis2.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis2) {
      @Override
      public String toString(Number object) {
        String label;
        label = String.format("%7.2f", object.floatValue());
        return label;
      }
    });

    final BarChart<String, Number> BarChart = new BarChart<String, Number>(xAxis2, yAxis2);

    BarChart.setAlternativeRowFillVisible(false);
    BarChart.setLegendVisible(false);
    BarChart.setAnimated(false);

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

    series2.getData().add(new XYChart.Data("Jan", 1));
    series2.getData().add(new XYChart.Data("Feb", 3));
    series2.getData().add(new XYChart.Data("Mar", 1.5));
    series2.getData().add(new XYChart.Data("Apr", 3));
    series2.getData().add(new XYChart.Data("May", 4.5));
    series2.getData().add(new XYChart.Data("Jun", 5));
    series2.getData().add(new XYChart.Data("Jul", 4));
    series2.getData().add(new XYChart.Data("Aug", 8));
    series2.getData().add(new XYChart.Data("Sep", 16.5));
    series2.getData().add(new XYChart.Data("Oct", 13.9));
    series2.getData().add(new XYChart.Data("Nov", 17));
    series2.getData().add(new XYChart.Data("Dec", 20));

    BarChart.getData().addAll(series2);

    pane2 = new BorderPane();
    pane2.setCenter(BarChart);

    Platform.runLater(new Runnable() {
      @Override
      public void run() {
        double percSplit;

        splitPane1.getItems().addAll(pane2);

        ObservableList<SplitPane.Divider> splitDiv = splitPane1.getDividers();

        percSplit = 1 / (double) (splitDiv.size() + 1);
        for (int i = 0; i < splitDiv.size(); i++) {
          splitPane1.setDividerPosition(i, percSplit);
          percSplit += 1 / (double) (splitDiv.size() + 1);
        }
      }
    });

    LV1 = LineBuilder.create()
            .strokeWidth(2)
            .stroke(Color.FORESTGREEN)
            .build();

    StackPane stack = new StackPane();
    Pane glassPane = new Pane();
    glassPane.getChildren().add(LV1);
    glassPane.minWidthProperty().bind(splitPane1.widthProperty());
    glassPane.minHeightProperty().bind(splitPane1.heightProperty());
    glassPane.setMouseTransparent(true);
    stack.getChildren().addAll(splitPane1, glassPane);
    Scene scene = new Scene(stack, 800, 600);
    LV1.endYProperty().bind(scene.heightProperty());
    stage.setScene(scene);
    pane1.setOnMouseMoved(mouseHandler);

    stage.show();
  }

  EventHandler<MouseEvent> mouseHandler = new EventHandler<MouseEvent>() {
    @Override public void handle(MouseEvent mouseEvent) {
      XYChart<Number, Number> chart1 = (XYChart<Number, Number>) pane1.getCenter();
      plotLine(chart1, LV1, mouseEvent.getX() + 1);
    }
  };

  private void plotLine(XYChart<Number, Number> chart, Line line, double x) {
    Axis xAxis = chart.getXAxis(), yAxis = chart.getYAxis();
    final double min = getSceneShift(xAxis);
    final double max = min + xAxis.getWidth();
    boolean setCrosshair = false;
    if (x > min && x < min + xAxis.getWidth()) {
      LV1.setStartX(x); LV1.setEndX(x);
      setCrosshair = true;
    } else if (x <= min){
      LV1.setStartX(min); LV1.setEndX(min);
    } else if (x >= max){
      LV1.setStartX(max); LV1.setEndX(max);
    }
    if (setCrosshair) {
      chart.setCursor(Cursor.CROSSHAIR);
    } else {
      chart.setCursor(Cursor.DEFAULT);
    }
  }

  private static double getSceneShift(Node node) {
    double shift = 0;
    do {
      shift += node.getLayoutX();
      node = node.getParent();
    } while (node != null);
    return shift;
  }

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

示例程序输出

于 2012-09-24T14:31:17.210 回答