2011-08-15 16 views
7

Cũng giống như đang được thực hiện trong ví dụ sau, tôi muốn các nhãn dấu tick vào lĩnh vực biểu đồ để thể xoay 45 độ như trong biểu đồ này: http://left.subtree.org/2007/08/14/rotate-labels-jfreechart/Làm cách nào để xoay nhãn đánh dấu trên tên miền của trục số trong JFreeChart?

Sự khác biệt là, tôi muốn làm điều này trên một âm mưu phân tán với một trục số. Tôi không thể tìm thấy một tương đương với setCategoryLabelPositions() trong lớp NumberAxis.

+1

tôi thấy mẫu này mã mà chỉ làm điều đó: http://www.jfree.org/phpBB2/viewtopic.php?f=3&t=18240&start= 15 – DrunkenPope

Trả lời

8

Phương pháp setVerticalTickLabels() có thể thay thế. Nếu không, tôi không thấy bất kỳ lựa chọn nào khác ngoài ghi đè refreshTicksHorizontal(). Xem thêm điều này 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

Điều này rất đơn giản và đủ tốt cho những gì tôi muốn. Cảm ơn. –

4

Bạn phải xem xét cấp độ siêu đẳng cấp: Axis.setLabelAngle(rad).

Và đây là example.

EDIT: ở trên không hữu ích, xin lỗi.

Tôi đã xem mã của org.jfreechart.chart.axis.NumberAxis.refreshTicksHorizontal. Có một góc được đặt là 0.0 (đối số cuối cùng trong tất cả các hàm tạo new NumberTick(...,0.0)). Bạn có thể tạo một lớp con của NumberAxis ghi đè phương thức refreshTicksHorizontal với một phương thức sử dụng một góc khác (được chỉ định trong hàm dựng của bạn).

Có vẻ như refreshTicks luôn được gọi khi vẽ biểu đồ, vì vậy bạn không phải lo lắng về việc nó không được gọi.

/** 
* 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

Đó là những gì tôi nghĩ ban đầu, nhưng điều đó không hiệu quả. Nó thay đổi nhãn cho trục, chứ không phải nhãn cho dấu tick. Mã bạn tham chiếu cũng gọi setCategoryLabelPositions() mà tôi đã tham chiếu ở trên. –

+0

@Jay Tôi đã cập nhật câu trả lời của mình. – toto2

+0

+1 Việc quản lý thuộc tính 'verticalTickLabels' rất đơn giản, nếu một chút _ad hoc_. – trashgod

9

Câu trả lời đầu tiên nhất định là một trục miền số. Nếu bạn có một trục thể loại, bạn muốn mã này:

CategoryAxis domainAxis = plot.getDomainAxis(); 
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90); 
Các vấn đề liên quan