Charts y轴倒置图表

Charts y轴倒置图表,charts,javafx-2,javafx,Charts,Javafx 2,Javafx,使用JavaFX图表,我需要反转堆叠区域图表的y轴,以便正零位于顶部,正数在y轴上向下工作。下面是我试图实现的一个模型 在JavaFX中实现这一点的最佳方法是什么(阅读:最短的开发时间和高代码重用) 更新 将数据转换为负数不是一个选项。我正在寻找适用于正数“未触及”的答案。您可以使用带负值的正则轴,但添加将删除减号的TickLabelFormatter final NumberAxis yAxis = new NumberAxis(-25, 0, 5); yAxis.setT

使用JavaFX图表,我需要反转堆叠区域图表的y轴,以便正零位于顶部,正数在y轴上向下工作。下面是我试图实现的一个模型

在JavaFX中实现这一点的最佳方法是什么(阅读:最短的开发时间和高代码重用)

更新


将数据转换为负数不是一个选项。我正在寻找适用于正数“未触及”的答案。

您可以使用带负值的正则轴,但添加将删除减号的
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));

简单的选项是启用轴上的
inverse()
操作。如果不修补JRE类,它是相当复杂的

有关如何处理此问题的一些提示:

1) 扩展值轴或轴(NumberAxis为最终值)

2) 将布尔字段和
inverse()
方法添加到axis类中

public void inverse() {
    inversed = !inversed; // boolean property
    invalidateRange();
    requestAxisLayout();
}
3) 如果扩展ValueAxis,则需要补偿超类应用的偏移(并截取轴大小发生变化的代码)

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) {
            }
        }
    }
}
@覆盖
受保护的void layoutChildren(){
最终侧=getSide();
布尔值isHorisontal=null==side | | side.isHorizontal();
this.offset=ISHORISTAL?getWidth():getHeight();
super.layoutChildren();
如果(反向){
double prevEnd=isHorisontal?offset+getTickLabelGap():0;
for(勾选m:getTickMarks()){
双位置=m.getPosition();
试一试{
final Text textNode=(Text)textNodeField.get(m);
final Bounds=textNode.getLayoutBounds();

如果(0使用轴的属性lowerBoundupperBound。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>


您是否建议我在图表中使用之前将所有数据转换为负数?是的。这当然不是最好的方法,但比使用反转功能扩展图表要快得多。为了避免数据的直接更新,您可以使用反转逻辑扩展
XYChart.data
类,或者引入实用方法w这将在图表中添加倒排数字。
<?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>