2013-12-03 6 views
4

Я использую JFreeChart XYPLot для построения набора XYData с разными метками. Я создал разные объекты XYSeries для разных меток, чтобы иметь разные цвета для разных меток. Теперь мне нужно потребовать изменения форм конкретных точек (тестовых данных) в каждом XYDataSeries, как показано ниже enter image description here. В приведенном выше графике есть два разных XYSeries с синим и красным цветом. Из этих двух мне нужно изменить формы некоторых точек (тестовые данные) на X вместо круга. Возможно ли это в JFreeChart. This post объяснить, как сделать это для всего набора данных, но я хочу изменить только определенные точкиИзменение формы одной точки в JFreeChart XYPLot

Ниже приведен код, который я написал до сих пор

public static Map<String, XYSeries> createXYSeries(Data[] dataSet){  
    Map<String,XYSeries> xySeries = new HashMap<String, XYSeries>();   
    for(Data data : dataSet){ 
     if(xySeries.get(data.actualLabel) == null){ 
      xySeries.put(data.actualLabel, new XYSeries(data.actualLabel)); 
     } 
     xySeries.get(data.actualLabel).add(data.dimensionValues[0],data.dimensionValues[1]); 
    } 

    return xySeries; 
} 

    public XYDataset createXYSeriesCollection(Map<String, XYSeries> plottingDataSet) { 
    XYSeriesCollection xySeriesCollection = new XYSeriesCollection(); 
    for (String key : plottingDataSet.keySet()) { 
     xySeriesCollection.addSeries(plottingDataSet.get(key)); 
    } 
    return xySeriesCollection; 
} 

    private ChartPanel createPlottingPanel(String title, 
     Map<String, XYSeries> plottingDataSet) { 
    JFreeChart jfreechart = ChartFactory.createScatterPlot(title, "X", "Y", 
      createSampleData(plottingDataSet), PlotOrientation.VERTICAL, 
      true, true, false); 
    XYPlot xyPlot = (XYPlot) jfreechart.getPlot(); 
    xyPlot.setDomainCrosshairVisible(true); 
    xyPlot.setRangeCrosshairVisible(true); 
    xyPlot.setBackgroundPaint(Color.white); 
    return new ChartPanel(jfreechart); 
} 

Примечание: Я пытаюсь построить результаты KNearestNeighbors . (Круги для данных поезда и Х для данных испытаний)

ответ

9

ChartFactory.createScatterPlot() создает экземпляр XYLineAndShapeRenderer. Вы можете заменить рендеринга на тот, который позволяет выборочно заменить Shape, возвращенный getItemShape(), как показано ниже.

xyPlot.setRenderer(new XYLineAndShapeRenderer(false, true) { 

     @Override 
     public Shape getItemShape(int row, int col) { 
      if (row == 0 & col == N) { 
       return ShapeUtilities.createDiagonalCross(5, 2); 
      } else { 
       return super.getItemShape(row, col); 
      } 
     } 
    }); 

image

Полный пример, в перспективе:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Shape; 
import java.util.*; 
import javax.swing.JFrame; 
import org.jfree.chart.*; 
import org.jfree.chart.axis.NumberAxis; 
import org.jfree.chart.axis.NumberTickUnit; 
import org.jfree.chart.plot.PlotOrientation; 
import org.jfree.chart.plot.XYPlot; 
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; 
import org.jfree.util.ShapeUtilities; 

/** 
* @see http://stackoverflow.com/a/20359200/230513 
* @see http://stackoverflow.com/a/6669529/230513 
*/ 
public class ScatterShape extends JFrame { 

    private static final int N = 8; 
    private static final int SIZE = 345; 
    private static final String title = "Scatter Shape Demo"; 
    private static final Random rand = new Random(); 
    private final XYSeries series = new XYSeries("Data"); 

    public ScatterShape(String s) { 
     super(s); 
     final ChartPanel chartPanel = createDemoPanel(); 
     this.add(chartPanel, BorderLayout.CENTER); 
    } 

    private ChartPanel createDemoPanel() { 
     JFreeChart chart = ChartFactory.createScatterPlot(
      title, "X", "Y", createSampleData(), 
      PlotOrientation.VERTICAL, true, true, false); 
     XYPlot xyPlot = (XYPlot) chart.getPlot(); 
     xyPlot.setDomainCrosshairVisible(true); 
     xyPlot.setRangeCrosshairVisible(true); 
     xyPlot.setRenderer(new XYLineAndShapeRenderer(false, true) { 

      @Override 
      public Shape getItemShape(int row, int col) { 
       if (row == 0 & col == N) { 
        return ShapeUtilities.createDiagonalCross(5, 2); 
       } else { 
        return super.getItemShape(row, col); 
       } 
      } 
     }); 
     adjustAxis((NumberAxis) xyPlot.getDomainAxis(), true); 
     adjustAxis((NumberAxis) xyPlot.getRangeAxis(), false); 
     xyPlot.setBackgroundPaint(Color.white); 
     return new ChartPanel(chart) { 

      @Override 
      public Dimension getPreferredSize() { 
       return new Dimension(SIZE, SIZE); 
      } 
     }; 
    } 

    private void adjustAxis(NumberAxis axis, boolean vertical) { 
     axis.setRange(-3.0, 3.0); 
     axis.setTickUnit(new NumberTickUnit(0.5)); 
     axis.setVerticalTickLabels(vertical); 
    } 

    private XYDataset createSampleData() { 
     XYSeriesCollection xySeriesCollection = new XYSeriesCollection(); 
     for (int i = 0; i < N * N; i++) { 
      series.add(rand.nextGaussian(), rand.nextGaussian()); 
     } 
     xySeriesCollection.addSeries(series); 
     return xySeriesCollection; 
    } 

    public static void main(String args[]) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       ScatterShape demo = new ScatterShape(title); 
       demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       demo.pack(); 
       demo.setLocationRelativeTo(null); 
       demo.setVisible(true); 
      } 
     }); 
    } 
} 
+0

Большое спасибо за ответ. Я хотел бы знать, есть ли способ изменить форму самого XYSeries, то есть установить другую форму для каждого XYSeries, вместо того, чтобы проверять каждую точку, к которой принадлежит XYSeries, а затем изменять форму. – Abhilash

+0

«XYSeries» в вашем наборе данных включает модель; рендерингом является вид. В представлении должна содержаться ссылка на модель, с помощью которой можно запросить модель для информации, необходимой ей для определения формы для рендеринга. – trashgod

+0

Это пересеченные пунктирные линии, нарисованные на графике, используя эти две строки кода xyPlot.setDomainCrosshairVisible (true); xyPlot.setRangeCrosshairVisible (true); меняется, я имею в виду, как я могу заблокировать его на 0,0 координаты независимо от щелчка мыши? – JAVA

Смежные вопросы