2013-08-02 5 views
5

JavaFX 차트를 사용하여 스택 된 영역 차트의 y 축을 반전시켜 양수 0이 맨 위에 있고 양수가 y 축에서 아래쪽으로 오도록해야합니다. 아래는 내가 달성하고자하는 것의 모형입니다.반전 된 Y 축이있는 차트

Inverted Y-Axis with positive numbers

최고 (읽기 : 짧은 개발 시간과 높은 코드 재사용) 란 자바 FX에서 이것을 달성하기 위해 방법은? 음수로 데이터를 변환

UPDATE

를 선택할 수 없습니다. 긍정적 인 숫자 인 "손길이 닿지 않는"답변을 찾고 있습니다.

답변

2

음수 값을 가진 일반 축을 사용할 수 있지만 빼기 기호를 제거하는 TickLabelFormatter을 추가하십시오.

final NumberAxis yAxis = new NumberAxis(-25, 0, 5); 

    yAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(yAxis) { 
     @Override 
     public String toString(Number value) { 
      // note we are printing minus value 
      return String.format("%7.1f", -value.doubleValue()); 
     } 
    }); 

    series1.getData().add(new XYChart.Data("Jan", -1)); 
    series1.getData().add(new XYChart.Data("Feb", -5)); 
    series1.getData().add(new XYChart.Data("Mar", -20)); 
+0

차트에서 사용하기 전에 모든 데이터를 음수로 변환 할 것을 제안합니까? – mawcsco

+0

예. 가장 좋은 방법은 아니지만 반전 기능으로 차트를 훨씬 빠르게 확장 할 수 있습니다. 데이터를 직접 업데이트하지 않으려면 반전 논리를 사용하여'XYChart.Data' 클래스를 확장하거나 차트에 반전 된 숫자를 추가하는 유틸리티 메소드를 도입하십시오. –

0

하지 쉬운 옵션은 축에 inverse() 동작을 가능하게하는 것입니다. JRE 클래스에 패치를 적용하지 않으면 매우 복잡합니다.

이 접근하는 방법에 대한 몇 가지 힌트 :

1) 확장 ValueAxis 또는 축 (NumberAxis이

2) 축 클래스에 부울 필드와 inverse() 방법을 추가) 불행하게도 최종

public void inverse() { 
    inversed = !inversed; // boolean property 
    invalidateRange(); 
    requestAxisLayout(); 
} 

3) ValueAxis를 확장 한 경우 - 수퍼 클래스에서 적용된 오프셋을 보정해야합니다 (축 크기가 변경되는 코드를 가로 채기).

@Override 
public Long getValueForDisplay(double displayPosition) { 
    if (inversed) 
     return super.getValueForDisplay(offset - displayPosition); 
    else 
     return super.getValueForDisplay(displayPosition); 
} 

@Override 
public double getDisplayPosition(Long value) { 
    if (inversed) 
     return offset - super.getDisplayPosition(value); 
    else 
     return super.getDisplayPosition(value); 
} 

4) (가장 못했던 부분) 숨기기 레이블 틱이 Axis 클래스에 의해 숨김 - 원래 구현은 틱의 기본 순서에 따라 달라집니다. 리플렉션을 통해 잠금을 해제하는 다른 방법을 찾지 못했습니다. 그래서 이것은 매우 부서지기 쉽습니다.

@Override 
protected void layoutChildren() { 
    final Side side = getSide(); 
    boolean isHorisontal = null == side || side.isHorizontal(); 
    this.offset = isHorisontal ? getWidth() : getHeight(); 
    super.layoutChildren(); 
    if (inversed) { 
     double prevEnd = isHorisontal ? offset + getTickLabelGap() : 0; 
     for (TickMark m : getTickMarks()) { 
      double position = m.getPosition(); 
      try { 
       final Text textNode = (Text) textNodeField.get(m); 
       final Bounds bounds = textNode.getLayoutBounds(); 
       if (0 <= position && position <= offset) 
        if (isHorisontal) { 
         textNode.setVisible(position < prevEnd); 
         prevEnd = position - (bounds.getWidth() + getTickLabelGap()); 
        } else { 
         textNode.setVisible(position > prevEnd); 
         prevEnd = position + (bounds.getHeight() + getTickLabelGap()); 
        } 
      } catch (IllegalAccessException ignored) { 
      } 
     } 
    } 
} 

Y 축이 예 this is how it looks like

0

사용 특성 LOWERBOUND와 축 UPPERBOUND 반전된다. lowerBound는 upperBound보다 커야합니다. fxml을 사용하는 방법은 다음과 같습니다.

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<HBox   
    prefHeight="600.0" 
    prefWidth="800.0" 
    xmlns:fx="http://javafx.com/fxml/1">  

    <javafx.scene.chart.LineChart 
     fx:id="chart" > 
     <xAxis > 
      <javafx.scene.chart.NumberAxis 
       label="X Axis" 
       lowerBound="0.01" 
       upperBound="100" 
       tickUnit="10" 
       autoRanging="false" /> 
     </xAxis> 
     <yAxis> 
      <javafx.scene.chart.NumberAxis 
        label="Y Axis" 
        lowerBound="100" 
        upperBound="0.001" 
        tickUnit="10" 
        autoRanging="false" 
       /> 
     </yAxis> 
    </javafx.scene.chart.LineChart>    
</Hbox> 
관련 문제