2012-11-13 39 views
2

我想在同一個數據上有兩個軸。在同一數據上的多個軸

該數據是幾個DefaultTableXYDatasets。該圖是一個XYPlot,我有兩個XYLineAndShapeRenderers和一個StackedXYAreaRenderer2

y值的所有數據都是以米爲單位的,我希望一個軸以米爲單位顯示,一個軸以英尺顯示。現在感覺這是一件很平常的事情,但我不能決定最明顯的做法。有效的方法之一是複製數據並以y爲單位,然後添加另一個NumberAxis並完成它。

但我認爲將NumberAxis作爲子類將會更明智,或者在NumberAxis中注入一些功能來擴展這些值。或者我應該採用第一種方法?

您認爲如何?

+2

在您的問題中用編程語言替換自然語言。一個更好的方式來開始這樣的對話:) –

+0

[demo](http://www.jfree.org/jfreechart/samples.html)有很多多軸的例子。 –

+0

是的,但我還沒有看到任何示例,其中一個數據集有多個軸。我可能會誤解,我會再次檢查它們 – bjarven

回答

2

最終我決定採用這種解決方案,它可能不是最優雅的,但它的工作。我有第二個軸feetAxis,並在名爲meterAxis的第一個軸上添加了一個AxisChangeListener。當meterAxis更改設置範圍feetAxis

我用SwingUtilities.invokeLater,否則當縮小圖表時範圍會不正確,然後feetAxis只會從0到1.沒有檢查爲什麼。

feetAxis = new NumberAxis("Height [ft]"); 
metersAxis = new NumberAxis("Height [m]"); 
pathPlot.setRangeAxis(0, metersAxis); 
pathPlot.setRangeAxis(1, feetAxis); 

metersAxis.addChangeListener(new AxisChangeListener() { 

    @Override 
    public void axisChanged(AxisChangeEvent event) { 

     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       feetAxis.setRange(metersAxis.getLowerBound() * MetersToFeet, metersAxis.getUpperBound() * MetersToFeet); 
       } 
      }); 
     } 
    }); 
1

爲避免重複數據,可以使用XYPlot方法mapDatasetToRangeAxes()將數據集索引映射到軸索引列表。在下面的例子中,meters是主軸,相應的軸的範圍相應地縮放,如here所示。需要注意的是invokeLater()需要確保feet軸的縮放之後的軸的任何變化都在meters軸上。

image

import java.awt.EventQueue; 
import java.util.Arrays; 
import java.util.List; 
import javax.swing.JFrame; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.axis.AxisLocation; 
import org.jfree.chart.axis.NumberAxis; 
import org.jfree.chart.axis.ValueAxis; 
import org.jfree.chart.event.AxisChangeEvent; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.chart.renderer.xy.XYItemRenderer; 
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; 
import org.jfree.data.xy.XYDataset; 
import org.jfree.data.xy.XYSeries; 
import org.jfree.data.xy.XYSeriesCollection; 

/** 
* @see https://stackoverflow.com/q/13358758/230513 
*/ 
public class AxisTest { 

    private static final int N = 5; 
    private static final double FEET_PER_METER = 3.28084; 

    private static XYDataset createDataset() { 
     XYSeriesCollection data = new XYSeriesCollection(); 
     final XYSeries series = new XYSeries("Data"); 
     for (int i = -N; i < N * N; i++) { 
      series.add(i, i); 
     } 
     data.addSeries(series); 
     return data; 
    } 

    private JFreeChart createChart(XYDataset dataset) { 
     NumberAxis meters = new NumberAxis("Meters"); 
     NumberAxis feet = new NumberAxis("Feet"); 
     ValueAxis domain = new NumberAxis(); 
     XYItemRenderer renderer = new XYLineAndShapeRenderer(); 
     XYPlot plot = new XYPlot(dataset, domain, meters, renderer); 
     plot.setRangeAxis(1, feet); 
     plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_LEFT); 
     List<Integer> axes = Arrays.asList(0, 1); 
     plot.mapDatasetToRangeAxes(0, axes); 
     scaleRange(feet, meters); 
     meters.addChangeListener((AxisChangeEvent event) -> { 
      EventQueue.invokeLater(() -> { 
       scaleRange(feet, meters); 
      }); 
     }); 
     JFreeChart chart = new JFreeChart("Axis Test", 
      JFreeChart.DEFAULT_TITLE_FONT, plot, true); 
     return chart; 
    } 

    private void scaleRange(NumberAxis feet, NumberAxis meters) { 
     feet.setRange(meters.getLowerBound() * FEET_PER_METER, 
      meters.getUpperBound() * FEET_PER_METER); 
    } 

    private void display() { 
     JFrame f = new JFrame("AxisTest"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(new ChartPanel(createChart(createDataset()))); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> { 
      new AxisTest().display(); 
     }); 
    } 
} 

或者,你可以使用一個JCheckBox兩個系列之間翻轉,米&腳,如本相關example。使用XYLineAndShapeRenderer可用的方法,您可以隱藏第二個系列的線條,形狀和圖例。該系列本身必須可見才能確定軸範圍。

相關問題