Prevent JFreeChart DialPlot wrapping around with large values?

落花浮王杯 提交于 2019-11-26 11:40:58

问题


My data value can vary between 0-100. I would like to display a JFreeChart DialPlot showing the range 0-30, where values larger than 30 are displayed by having the needle fixed at 30 but the true value displayed on the dial.

The image below shows what my example code currently produces:

Current Output

\"dial

Here I am displaying the value 50. The dial has wrapped around to point at 14. I would prefer it to be set to the maximum (30), much like with a fuel dial:

Desired Output

\"enter

Is this possible with JFreeChart? SSCCE code below.

public class DemoChartProblem {

  private final DefaultValueDataset dataset = new DefaultValueDataset(50);
  private final JFrame frame = new JFrame();

  public static void main(String[] args) throws Exception {
    new DemoChartProblem();
  }

  public DemoChartProblem() {
    frame.setPreferredSize(new Dimension(300, 300));
    frame.add(buildDialPlot(0, 30, 5));
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        frame.setVisible(true);
      }
    });
  }

  private ChartPanel buildDialPlot(int minimumValue, int maximumValue,
      int majorTickGap) {

    DialPlot plot = new DialPlot(dataset);
    plot.setDialFrame(new StandardDialFrame());
    plot.addLayer(new DialValueIndicator(0));
    plot.addLayer(new DialPointer.Pointer());

    StandardDialScale scale = new StandardDialScale(minimumValue, maximumValue,
        -120, -300, majorTickGap, majorTickGap - 1);
    scale.setTickRadius(0.88);
    scale.setTickLabelOffset(0.20);
    plot.addScale(0, scale);

    return new ChartPanel(new JFreeChart(plot));
  }
}

回答1:


I would be interested to hear if there are better methods.

The disparity between the DialValueIndicator and the maximumValue may be confusing. As an alternative, signify distinct ranges using StandardDialRange:

int redLine = 3 * maximumValue / 5;
plot.addLayer(new StandardDialRange(minimumValue, redLine, Color.blue));
plot.addLayer(new StandardDialRange(redLine, maximumValue, Color.red));

Setting the frame's preferred size is problematic. Instead, override the getPreferredSize() method of ChartPanel:

return new ChartPanel(new JFreeChart(plot)) {
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(300, 300);
    }
};




回答2:


I've just figured out a work-around answer, but I would be interested to hear if there are better methods.

In this solution, I maintain two DefaultValueDataset objects. One contains the real value and one contains a constrained value, no larger than my dial limit. The needle is associated with the constrained set and the dial value is linked to the real value.

public class DemoChartProblem {

  private static final int DISPLAY_MAX = 30;
  private final DefaultValueDataset dataset = new DefaultValueDataset();
  private final DefaultValueDataset displayDataset = new DefaultValueDataset();
  private final JFrame frame = new JFrame();

  public static void main(String[] args) throws Exception {
    new DemoChartProblem();
  }

  public DemoChartProblem() {
    frame.setPreferredSize(new Dimension(300, 300));
    frame.add(buildDialPlot(0, DISPLAY_MAX, 5));
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    setValue(50);

    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        frame.setVisible(true);
      }
    });
  }

  private void setValue(int value) {
    dataset.setValue(value);
    displayDataset.setValue(Math.min(DISPLAY_MAX, value));
  }

  private ChartPanel buildDialPlot(int minimumValue, int maximumValue,
      int majorTickGap) {

    DialPlot plot = new DialPlot();
    plot.setDataset(0, dataset);
    plot.setDataset(1, displayDataset);

    plot.setDialFrame(new StandardDialFrame());

    // value indicator uses the real data set
    plot.addLayer(new DialValueIndicator(0));

    // needle uses constrained data set
    plot.addLayer(new DialPointer.Pointer(1));

    StandardDialScale scale = new StandardDialScale(minimumValue, maximumValue,
        -120, -300, majorTickGap, majorTickGap - 1);
    scale.setTickRadius(0.88);
    scale.setTickLabelOffset(0.20);
    plot.addScale(0, scale);

    return new ChartPanel(new JFreeChart(plot));
  }
}


来源:https://stackoverflow.com/questions/16163964/prevent-jfreechart-dialplot-wrapping-around-with-large-values

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!