【问题标题】:How do I rotate tick mark labels on the domain of a number axis in JFreeChart?如何在 JFreeChart 中的数字轴域上旋转刻度线标签?
【发布时间】:2011-10-27 14:46:39
【问题描述】:

就像在以下示例中所做的那样,我希望图表域上的刻度线标签旋转 45 度,就像在此图表中一样: http://left.subtree.org/2007/08/14/rotate-labels-jfreechart/

不同之处在于,我想在带有数字轴的散点图上执行此操作。我在 NumberAxis 类中找不到与 setCategoryLabelPositions() 等效的方法。

【问题讨论】:

    标签: java axis jfreechart


    【解决方案1】:

    给出的第一个答案是针对数字域轴。如果你有一个类别轴,你想要这个代码:

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

    【讨论】:

      【解决方案2】:

      setVerticalTickLabels() 方法可能是一种替代方法。如果没有,我看不到任何选择,只能覆盖refreshTicksHorizontal()。另请参阅example

      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);
          }
      }
      

      【讨论】:

      • 这非常简单,足以满足我的需求。谢谢。
      【解决方案3】:

      你要看看超类:Axis.setLabelAngle(rad)

      这里是example

      编辑:以上没有用,抱歉。

      看了org.jfreechart.chart.axis.NumberAxis.refreshTicksHorizo​​ntal的代码。实际上有一个角度设置为 0.0(所有 new NumberTick(...,0.0) 构造函数中的最后一个参数)。您可以创建一个 NumberAxis 的子类,用一个使用不同角度(在您的构造函数中指定)的方法覆盖方法 refreshTicksHorizo​​ntal。

      好像在绘制图形的时候总是会调用refreshTicks,所以不用担心没被调用。

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

      【讨论】:

      • 我原本也是这么想的,但是不行。它更改轴的标签,而不是刻度线的标签。您引用的代码还调用了我在上面引用的 setCategoryLabelPositions()。
      • +1 控制verticalTickLabels 属性很简单,如果有点ad hoc
      • @toto 谢谢,这可行,但在升级到较新版本的 JFreeChart 时可能会中断。
      • @Jay 我昨天下载了它。自 2009 年以来未更新。
      • @toto 真。出于各种原因,我们实际上使用的是旧版本,尽管我们将来可能会升级。我确实给了你一个 +1,因为你的解决方案有效并且可能对其他人更好。
      猜你喜欢
      • 2015-05-04
      • 1970-01-01
      • 1970-01-01
      • 2020-08-05
      • 2015-11-21
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      相关资源
      最近更新 更多