2011-08-15 28 views
7

Al igual que se hace en el siguiente ejemplo, quiero las etiquetas las marcas de graduación en el dominio de la carta para ser girado 45 grados como el son en este gráfico: http://left.subtree.org/2007/08/14/rotate-labels-jfreechart/¿Cómo giro las etiquetas de marca en el dominio de un eje numérico en JFreeChart?

La diferencia es, yo quiero hacer esto en un diagrama de dispersión con un eje numérico. No puedo encontrar un equivalente a setCategoryLabelPositions() en la clase NumberAxis.

+1

me encontré con este código de ejemplo, que hace precisamente eso: http://www.jfree.org/phpBB2/viewtopic.php?f=3&t=18240&start= 15 – DrunkenPope

Respuesta

8

El método setVerticalTickLabels() puede ser una alternativa. Si no, no veo otra opción más que anular refreshTicksHorizontal(). Vea también esto example.

enter image description here

import java.awt.Color; 
import java.awt.Dimension; 
import java.util.*; 
import org.jfree.chart.*; 
import org.jfree.chart.axis.NumberAxis; 
import org.jfree.chart.plot.PlotOrientation; 
import org.jfree.chart.plot.XYPlot; 
import org.jfree.chart.renderer.xy.XYItemRenderer; 
import org.jfree.data.xy.XYDataset; 
import org.jfree.data.xy.XYSeries; 
import org.jfree.data.xy.XYSeriesCollection; 
import org.jfree.ui.ApplicationFrame; 
import org.jfree.ui.RefineryUtilities; 

/** 
* @see https://stackoverflow.com/questions/7208657 
* @see https://stackoverflow.com/questions/7071057 
*/ 
public class ScatterTickLabels extends ApplicationFrame { 

    public ScatterTickLabels(String s) { 
     super(s); 
     final ChartPanel chartPanel = createDemoPanel(); 
     chartPanel.setPreferredSize(new Dimension(640, 480)); 
     this.add(chartPanel); 
    } 

    public static ChartPanel createDemoPanel() { 
     JFreeChart jfreechart = ChartFactory.createScatterPlot(
      "Scatter Plot Demo", "X", "Y", samplexydataset(), 
      PlotOrientation.VERTICAL, true, true, false); 
     XYPlot xyPlot = (XYPlot) jfreechart.getPlot(); 
     xyPlot.setDomainCrosshairVisible(true); 
     xyPlot.setRangeCrosshairVisible(true); 
     XYItemRenderer renderer = xyPlot.getRenderer(); 
     renderer.setSeriesPaint(0, Color.blue); 
     NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis(); 
     domain.setVerticalTickLabels(true); 
     return new ChartPanel(jfreechart); 
    } 

    private static XYDataset samplexydataset() { 
     int cols = 20; 
     int rows = 20; 
     XYSeriesCollection xySeriesCollection = new XYSeriesCollection(); 
     XYSeries series = new XYSeries("Random"); 
     Random rand = new Random(); 
     for (int i = 0; i < rows; i++) { 
      for (int j = 0; j < cols; j++) { 
       double x = rand.nextGaussian(); 
       double y = rand.nextGaussian(); 
       series.add(x, y); 
      } 
     } 
     xySeriesCollection.addSeries(series); 
     return xySeriesCollection; 
    } 

    public static void main(String args[]) { 
     ScatterTickLabels demo = new ScatterTickLabels("Scatter Plot Demo"); 
     demo.pack(); 
     RefineryUtilities.centerFrameOnScreen(demo); 
     demo.setVisible(true); 
    } 
} 
+0

Esto es muy simple y es lo suficientemente bueno para lo que quiero. Gracias. –

4

Tienes que mirar la súper clase: Axis.setLabelAngle(rad).

Y aquí hay un example.

EDIT: de arriba no fue útil, lo siento.

Miré el código de org.jfreechart.chart.axis.NumberAxis.refreshTicksHorizontal. En realidad, hay un ángulo que se establece en 0.0 (el último argumento en todos los constructores new NumberTick(...,0.0)). Podría hacer una subclase de NumberAxis que anule el método refreshTicksHorizontal con uno que use un ángulo diferente (especificado en su constructor).

Parece que siempre se llama a refreshTicks cuando se dibuja el gráfico, por lo que no tiene que preocuparse de que no se lo llame.

/** 
* Calculates the positions of the tick labels for the axis, storing the 
* results in the tick label list (ready for drawing). 
* 
* @param g2 the graphics device. 
* @param dataArea the area in which the data should be drawn. 
* @param edge the location of the axis. 
* 
* @return A list of ticks. 
*/ 
protected List refreshTicksHorizontal(Graphics2D g2, 
     Rectangle2D dataArea, RectangleEdge edge) { 

    List result = new java.util.ArrayList(); 

    Font tickLabelFont = getTickLabelFont(); 
    g2.setFont(tickLabelFont); 

    if (isAutoTickUnitSelection()) { 
     selectAutoTickUnit(g2, dataArea, edge); 
    } 

    TickUnit tu = getTickUnit(); 
    double size = tu.getSize(); 
    int count = calculateVisibleTickCount(); 
    double lowestTickValue = calculateLowestVisibleTickValue(); 

    if (count <= ValueAxis.MAXIMUM_TICK_COUNT) { 
     int minorTickSpaces = getMinorTickCount(); 
     if (minorTickSpaces <= 0) { 
      minorTickSpaces = tu.getMinorTickCount(); 
     } 
     for (int minorTick = 1; minorTick < minorTickSpaces; minorTick++) { 
      double minorTickValue = lowestTickValue 
        - size * minorTick/minorTickSpaces; 
      if (getRange().contains(minorTickValue)){ 
       result.add(new NumberTick(TickType.MINOR, minorTickValue, 
         "", TextAnchor.TOP_CENTER, TextAnchor.CENTER, 
         0.0)); 
      } 
     } 
     for (int i = 0; i < count; i++) { 
      double currentTickValue = lowestTickValue + (i * size); 
      String tickLabel; 
      NumberFormat formatter = getNumberFormatOverride(); 
      if (formatter != null) { 
       tickLabel = formatter.format(currentTickValue); 
      } 
      else { 
       tickLabel = getTickUnit().valueToString(currentTickValue); 
      } 
      TextAnchor anchor = null; 
      TextAnchor rotationAnchor = null; 
      double angle = 0.0; 
      if (isVerticalTickLabels()) { 
       anchor = TextAnchor.CENTER_RIGHT; 
       rotationAnchor = TextAnchor.CENTER_RIGHT; 
       if (edge == RectangleEdge.TOP) { 
        angle = Math.PI/2.0; 
       } 
       else { 
        angle = -Math.PI/2.0; 
       } 
      } 
      else { 
       if (edge == RectangleEdge.TOP) { 
        anchor = TextAnchor.BOTTOM_CENTER; 
        rotationAnchor = TextAnchor.BOTTOM_CENTER; 
       } 
       else { 
        anchor = TextAnchor.TOP_CENTER; 
        rotationAnchor = TextAnchor.TOP_CENTER; 
       } 
      } 

      Tick tick = new NumberTick(new Double(currentTickValue), 
        tickLabel, anchor, rotationAnchor, angle); 
      result.add(tick); 
      double nextTickValue = lowestTickValue + ((i + 1)* size); 
      for (int minorTick = 1; minorTick < minorTickSpaces; 
        minorTick++) { 
       double minorTickValue = currentTickValue 
         + (nextTickValue - currentTickValue) 
         * minorTick/minorTickSpaces; 
       if (getRange().contains(minorTickValue)){ 
        result.add(new NumberTick(TickType.MINOR, 
          minorTickValue, "", TextAnchor.TOP_CENTER, 
          TextAnchor.CENTER, 0.0)); 
       } 
      } 
     } 
    } 
    return result; 

} 
+1

Eso es lo que originalmente pensé también, pero eso no funciona. Cambia la etiqueta para el eje, no las etiquetas para las marcas. El código al que hace referencia también llama a setCategoryLabelPositions() al que hice referencia arriba. –

+0

@Jay Actualicé mi respuesta. – toto2

+0

+1 Comando de la propiedad 'verticalTickLabels' es simple, aunque un poco _ad hoc_. – trashgod

9

La primera respuesta dada es para un eje dominio numérico. Si usted tiene un eje de categorías, desea que este código:

CategoryAxis domainAxis = plot.getDomainAxis(); 
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); 
Cuestiones relacionadas