📄 thermometerplot.java
字号:
/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2004, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* --------------------
* ThermometerPlot.java
* --------------------
*
* (C) Copyright 2000-2004, by Bryan Scott and Contributors.
*
* Original Author: Bryan Scott (based on MeterPlot by Hari).
* Contributor(s): David Gilbert (for Object Refinery Limited).
* Arnaud Lelievre;
*
* Changes
* -------
* 11-Apr-2002 : Version 1, contributed by Bryan Scott;
* 15-Apr-2002 : Changed to implement VerticalValuePlot;
* 29-Apr-2002 : Added getVerticalValueAxis() method (DG);
* 25-Jun-2002 : Removed redundant imports (DG);
* 17-Sep-2002 : Reviewed with Checkstyle utility (DG);
* 18-Sep-2002 : Extensive changes made to API, to iron out bugs and inconsistencies (DG);
* 13-Oct-2002 : Corrected error datasetChanged which would generate exceptions when value set
* to null (BRS).
* 23-Jan-2003 : Removed one constructor (DG);
* 26-Mar-2003 : Implemented Serializable (DG);
* 02-Jun-2003 : Removed test for compatible range axis (DG);
* 01-Jul-2003 : Added additional check in draw method to ensure value not null (BRS);
* 08-Sep-2003 : Added internationalization via use of properties resourceBundle (RFE 690236) (AL);#
* 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
* 29-Sep-2003 : Updated draw to set value of cursor to non-zero and allow painting of axis.
* An incomplete fix and needs to be set for left or right drawing (BRS);
* 19-Nov-2003 : Added support for value labels to be displayed left of the thermometer
* 19-Nov-2003 : Improved axis drawing (now default axis does not draw axis line
* and is closer to the bulb). Added support for the positioning
* of the axis to the left or right of the bulb. (BRS);
* 03-Dec-2003 : Directly mapped deprecated setData()/getData() method to get/setDataset() (TM);
* 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
* 07-Apr-2004 : Changed string width calculation (DG);
*
*/
package org.jfree.chart.plot;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.List;
import java.util.ResourceBundle;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.PlotChangeEvent;
import org.jfree.data.Range;
import org.jfree.data.general.DatasetChangeEvent;
import org.jfree.data.general.DefaultValueDataset;
import org.jfree.data.general.ValueDataset;
import org.jfree.io.SerialUtilities;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.Spacer;
import org.jfree.util.ObjectUtils;
/**
* A plot that displays a single value (from a {@link ValueDataset}) in a thermometer type display.
* <p>
* This plot supports a number of options:
* <ol>
* <li>three sub-ranges which could be viewed as 'Normal', 'Warning' and 'Critical' ranges.</li>
* <li>the thermometer can be run in two modes:
* <ul>
* <li>fixed range, or</li>
* <li>range adjusts to current sub-range.</li>
* </ul>
* </li>
* <li>settable units to be displayed.</li>
* <li>settable display location for the value text.</li>
* </ol>
*
* @author Bryan Scott
*/
public class ThermometerPlot
extends Plot
implements ValueAxisPlot,
Cloneable,
Serializable {
/** A constant for unit type 'None'. */
public static final int UNITS_NONE = 0;
/** A constant for unit type 'Fahrenheit'. */
public static final int UNITS_FAHRENHEIT = 1;
/** A constant for unit type 'Celcius'. */
public static final int UNITS_CELCIUS = 2;
/** A constant for unit type 'Kelvin'. */
public static final int UNITS_KELVIN = 3;
/** A constant for the value label position (no label). */
public static final int NONE = 0;
/** A constant for the value label position (right of the thermometer). */
public static final int RIGHT = 1;
/** A constant for the value label position (left of the thermometer). */
public static final int LEFT = 2;
/** A constant for the value label position (in the thermometer bulb). */
public static final int BULB = 3;
/** A constant for the 'normal' range. */
public static final int NORMAL = 0;
/** A constant for the 'warning' range. */
public static final int WARNING = 1;
/** A constant for the 'critical' range. */
public static final int CRITICAL = 2;
/** The bulb radius. */
protected static final int BULB_RADIUS = 40;
/** The bulb diameter. */
protected static final int BULB_DIAMETER = BULB_RADIUS * 2;
/** The column radius. */
protected static final int COLUMN_RADIUS = 20;
/** The column diameter.*/
protected static final int COLUMN_DIAMETER = COLUMN_RADIUS * 2;
/** The gap radius. */
protected static final int GAP_RADIUS = 5;
/** The gap diameter. */
protected static final int GAP_DIAMETER = GAP_RADIUS * 2;
/** The axis gap. */
protected static final int AXIS_GAP = 10;
/** The unit strings. */
protected static final String[] UNITS = {
"", "\u00B0F", "\u00B0C", "\u00B0K"};
/** Index for low value in subrangeInfo matrix. */
protected static final int RANGE_LOW = 0;
/** Index for high value in subrangeInfo matrix. */
protected static final int RANGE_HIGH = 1;
/** Index for display low value in subrangeInfo matrix. */
protected static final int DISPLAY_LOW = 2;
/** Index for display high value in subrangeInfo matrix. */
protected static final int DISPLAY_HIGH = 3;
/** The default lower bound. */
protected static final double DEFAULT_LOWER_BOUND = 0.0;
/** The default upper bound. */
protected static final double DEFAULT_UPPER_BOUND = 100.0;
/** The dataset for the plot. */
private ValueDataset dataset;
/** The range axis. */
private ValueAxis rangeAxis;
/** The lower bound for the thermometer. */
private double lowerBound = DEFAULT_LOWER_BOUND;
/** The upper bound for the thermometer. */
private double upperBound = DEFAULT_UPPER_BOUND;
/** Blank space inside the plot area around the outside of the thermometer. */
private Spacer padding;
/** Stroke for drawing the thermometer */
private transient Stroke thermometerStroke = new BasicStroke(1.0f);
/** Paint for drawing the thermometer */
private transient Paint thermometerPaint = Color.black;
/** The display units */
private int units = UNITS_CELCIUS;
/** The value label position. */
private int valueLocation = BULB;
/** The position of the axis **/
private int axisLocation = LEFT;
/** The font to write the value in */
private Font valueFont = new Font("SansSerif", Font.BOLD, 16);
/** Colour that the value is written in */
private transient Paint valuePaint = Color.white;
/** Number format for the value */
private NumberFormat valueFormat = new DecimalFormat();
/** The default paint for the mercury in the thermometer. */
private transient Paint mercuryPaint = Color.lightGray;
/** A flag that controls whether value lines are drawn. */
private boolean showValueLines = false;
/** The display sub-range. */
private int subrange = -1;
/** The start and end values for the subranges. */
private double[][] subrangeInfo = {
{
0.0, 50.0, 0.0, 50.0}
, {
50.0, 75.0, 50.0, 75.0}
, {
75.0, 100.0, 75.0, 100.0}
};
/** A flag that controls whether or not the axis range adjusts to the sub-ranges. */
private boolean followDataInSubranges = false;
/** A flag that controls whether or not the mercury paint changes with the subranges. */
private boolean useSubrangePaint = true;
/** Paint for each range */
private Paint[] subrangePaint = {
Color.green,
Color.orange,
Color.red
};
/** A flag that controls whether the sub-range indicators are visible. */
private boolean subrangeIndicatorsVisible = true;
/** The stroke for the sub-range indicators. */
private transient Stroke subrangeIndicatorStroke = new BasicStroke(2.0f);
/** The range indicator stroke. */
private transient Stroke rangeIndicatorStroke = new BasicStroke(3.0f);
/** The resourceBundle for the localization. */
protected static ResourceBundle localizationResources =
ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
/**
* Creates a new thermometer plot.
*/
public ThermometerPlot() {
this(new DefaultValueDataset());
}
/**
* Creates a new thermometer plot, using default attributes where necessary.
*
* @param dataset the data set.
*/
public ThermometerPlot(ValueDataset dataset) {
super();
this.padding = new Spacer(Spacer.RELATIVE, 0.05, 0.05, 0.05, 0.05);
this.dataset = dataset;
if (dataset != null) {
dataset.addChangeListener(this);
}
NumberAxis axis = new NumberAxis(null);
axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
axis.setAxisLineVisible(false);
setRangeAxis(axis);
setAxisRange();
}
/**
* Returns the primary dataset for the plot.
*
* @return The primary dataset (possibly <code>null</code>).
*/
public ValueDataset getDataset() {
return this.dataset;
}
/**
* Sets the dataset for the plot, replacing the existing dataset if there is one.
*
* @param dataset the dataset (<code>null</code> permitted).
*/
public void setDataset(ValueDataset dataset) {
// if there is an existing dataset, remove the plot from the list of change listeners...
ValueDataset existing = this.dataset;
if (existing != null) {
existing.removeChangeListener(this);
}
// set the new dataset, and register the chart as a change listener...
this.dataset = dataset;
if (dataset != null) {
setDatasetGroup(dataset.getGroup());
dataset.addChangeListener(this);
}
// send a dataset change event to self...
DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
datasetChanged(event);
}
/**
* Returns the dataset cast to {@link ValueDataset} (provided for convenience).
*
* @return the dataset for the plot, cast as a {@link ValueDataset}.
*
* @deprecated Use getDataset() instead.
*/
public ValueDataset getData() {
return getDataset();
}
/**
* Sets the data for the chart, replacing any existing data.
* <P>
* Registered listeners are notified that the plot has been modified (this will normally
* trigger a chart redraw).
*
* @param dataset the new dataset.
*
* @deprecated Use setDataset(...) instead.
*/
public void setData(ValueDataset dataset) {
setDataset(dataset);
}
/**
* Returns the range axis.
*
* @return the range axis.
*/
public ValueAxis getRangeAxis() {
return this.rangeAxis;
}
/**
* Sets the range axis for the plot.
* <P>
* An exception is thrown if the new axis and the plot are not mutually compatible.
*
* @param axis the new axis.
*/
public void setRangeAxis(ValueAxis axis) {
if (axis != null) {
axis.setPlot(this);
axis.addChangeListener(this);
}
// plot is likely registered as a listener with the existing axis...
if (this.rangeAxis != null) {
this.rangeAxis.removeChangeListener(this);
}
this.rangeAxis = axis;
}
/**
* Returns the lower bound for the thermometer.
* <p>
* The data value can be set lower than this, but it will not be shown in the thermometer.
*
* @return the lower bound.
*
*/
public double getLowerBound() {
return this.lowerBound;
}
/**
* Sets the lower bound for the thermometer.
*
* @param lower the lower bound.
*/
public void setLowerBound(double lower) {
this.lowerBound = lower;
setAxisRange();
}
/**
* Returns the upper bound for the thermometer.
* <p>
* The data value can be set higher than this, but it will not be shown in the thermometer.
*
* @return the upper bound.
*
*/
public double getUpperBound() {
return this.upperBound;
}
/**
* Sets the upper bound for the thermometer.
*
* @param upper the upper bound.
*/
public void setUpperBound(double upper) {
this.upperBound = upper;
setAxisRange();
}
/**
* Sets the lower and upper bounds for the thermometer.
*
* @param lower the lower bound.
* @param upper the upper bound.
*/
public void setRange(double lower, double upper) {
this.lowerBound = lower;
this.upperBound = upper;
setAxisRange();
}
/**
* Returns the padding for the thermometer. This is the space inside the plot area.
*
* @return the padding.
*/
public Spacer getPadding() {
return this.padding;
}
/**
* Sets the padding for the thermometer.
*
* @param padding the padding.
*/
public void setPadding(Spacer padding) {
this.padding = padding;
notifyListeners(new PlotChangeEvent(this));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -