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