📄 meterplot.java
字号:
Polygon arrow = new Polygon();
if ((valueAngle > 135 && valueAngle < 225)
|| (valueAngle < 45 && valueAngle > -45)) {
double valueP3 = (meterMiddleY
- DEFAULT_CIRCLE_SIZE / 4);
double valueP4 = (meterMiddleY
+ DEFAULT_CIRCLE_SIZE / 4);
arrow.addPoint((int) meterMiddleX, (int) valueP3);
arrow.addPoint((int) meterMiddleX, (int) valueP4);
}
else {
arrow.addPoint((int) (meterMiddleX
- DEFAULT_CIRCLE_SIZE / 4), (int) meterMiddleY);
arrow.addPoint((int) (meterMiddleX
+ DEFAULT_CIRCLE_SIZE / 4), (int) meterMiddleY);
}
arrow.addPoint((int) valueP1, (int) valueP2);
g2.fill(arrow);
Ellipse2D circle = new Ellipse2D.Double(meterMiddleX
- DEFAULT_CIRCLE_SIZE / 2, meterMiddleY
- DEFAULT_CIRCLE_SIZE / 2, DEFAULT_CIRCLE_SIZE,
DEFAULT_CIRCLE_SIZE);
g2.fill(circle);
}
}
g2.setClip(savedClip);
g2.setComposite(originalComposite);
}
if (this.drawBorder) {
drawOutline(g2, area);
}
}
/**
* Draws the arc to represent an interval.
*
* @param g2 the graphics device.
* @param meterArea the drawing area.
* @param interval the interval.
*/
protected void drawArcForInterval(Graphics2D g2, Rectangle2D meterArea,
MeterInterval interval) {
double minValue = interval.getRange().getLowerBound();
double maxValue = interval.getRange().getUpperBound();
Paint outlinePaint = interval.getOutlinePaint();
Stroke outlineStroke = interval.getOutlineStroke();
Paint backgroundPaint = interval.getBackgroundPaint();
if (backgroundPaint != null) {
fillArc(g2, meterArea, minValue, maxValue, backgroundPaint, false);
}
if (outlinePaint != null) {
if (outlineStroke != null) {
drawArc(g2, meterArea, minValue, maxValue, outlinePaint,
outlineStroke);
}
drawTick(g2, meterArea, minValue, true);
drawTick(g2, meterArea, maxValue, true);
}
}
/**
* Draws an arc.
*
* @param g2 the graphics device.
* @param area the plot area.
* @param minValue the minimum value.
* @param maxValue the maximum value.
* @param paint the paint.
* @param stroke the stroke.
*/
protected void drawArc(Graphics2D g2, Rectangle2D area, double minValue,
double maxValue, Paint paint, Stroke stroke) {
double startAngle = valueToAngle(maxValue);
double endAngle = valueToAngle(minValue);
double extent = endAngle - startAngle;
double x = area.getX();
double y = area.getY();
double w = area.getWidth();
double h = area.getHeight();
g2.setPaint(paint);
g2.setStroke(stroke);
if (paint != null && stroke != null) {
Arc2D.Double arc = new Arc2D.Double(x, y, w, h, startAngle,
extent, Arc2D.OPEN);
g2.setPaint(paint);
g2.setStroke(stroke);
g2.draw(arc);
}
}
/**
* Fills an arc on the dial between the given values.
*
* @param g2 the graphics device.
* @param area the plot area.
* @param minValue the minimum data value.
* @param maxValue the maximum data value.
* @param paint the background paint (<code>null</code> not permitted).
* @param dial a flag that indicates whether the arc represents the whole
* dial.
*/
protected void fillArc(Graphics2D g2, Rectangle2D area,
double minValue, double maxValue, Paint paint,
boolean dial) {
if (paint == null) {
throw new IllegalArgumentException("Null 'paint' argument");
}
double startAngle = valueToAngle(maxValue);
double endAngle = valueToAngle(minValue);
double extent = endAngle - startAngle;
double x = area.getX();
double y = area.getY();
double w = area.getWidth();
double h = area.getHeight();
int joinType = Arc2D.OPEN;
if (this.shape == DialShape.PIE) {
joinType = Arc2D.PIE;
}
else if (this.shape == DialShape.CHORD) {
if (dial && this.meterAngle > 180) {
joinType = Arc2D.CHORD;
}
else {
joinType = Arc2D.PIE;
}
}
else if (this.shape == DialShape.CIRCLE) {
joinType = Arc2D.PIE;
if (dial) {
extent = 360;
}
}
else {
throw new IllegalStateException("DialShape not recognised.");
}
g2.setPaint(paint);
Arc2D.Double arc = new Arc2D.Double(x, y, w, h, startAngle, extent,
joinType);
g2.fill(arc);
}
/**
* Translates a data value to an angle on the dial.
*
* @param value the value.
*
* @return The angle on the dial.
*/
public double valueToAngle(double value) {
value = value - this.range.getLowerBound();
double baseAngle = 180 + ((this.meterAngle - 180) / 2);
return baseAngle - ((value / this.range.getLength()) * this.meterAngle);
}
/**
* Draws the ticks that subdivide the overall range.
*
* @param g2 the graphics device.
* @param meterArea the meter area.
* @param minValue the minimum value.
* @param maxValue the maximum value.
*/
protected void drawTicks(Graphics2D g2, Rectangle2D meterArea,
double minValue, double maxValue) {
for (double v = minValue; v <= maxValue; v += this.tickSize) {
drawTick(g2, meterArea, v);
}
}
/**
* Draws a tick.
*
* @param g2 the graphics device.
* @param meterArea the meter area.
* @param value the value.
*/
protected void drawTick(Graphics2D g2, Rectangle2D meterArea,
double value) {
drawTick(g2, meterArea, value, false);
}
/**
* Draws a tick on the dial.
*
* @param g2 the graphics device.
* @param meterArea the meter area.
* @param value the tick value.
* @param label a flag that controls whether or not a value label is drawn.
*/
protected void drawTick(Graphics2D g2, Rectangle2D meterArea,
double value, boolean label) {
double valueAngle = valueToAngle(value);
double meterMiddleX = meterArea.getCenterX();
double meterMiddleY = meterArea.getCenterY();
g2.setPaint(this.tickPaint);
g2.setStroke(new BasicStroke(2.0f));
double valueP2X = 0;
double valueP2Y = 0;
double radius = (meterArea.getWidth() / 2) + DEFAULT_BORDER_SIZE;
double radius1 = radius - 15;
double valueP1X = meterMiddleX
+ (radius * Math.cos(Math.PI * (valueAngle / 180)));
double valueP1Y = meterMiddleY
- (radius * Math.sin(Math.PI * (valueAngle / 180)));
valueP2X = meterMiddleX
+ (radius1 * Math.cos(Math.PI * (valueAngle / 180)));
valueP2Y = meterMiddleY
- (radius1 * Math.sin(Math.PI * (valueAngle / 180)));
Line2D.Double line = new Line2D.Double(valueP1X, valueP1Y, valueP2X,
valueP2Y);
g2.draw(line);
if (this.tickLabelsVisible && label) {
String tickLabel = this.tickLabelFormat.format(value);
g2.setFont(this.tickLabelFont);
g2.setPaint(this.tickLabelPaint);
FontMetrics fm = g2.getFontMetrics();
Rectangle2D tickLabelBounds
= TextUtilities.getTextBounds(tickLabel, g2, fm);
double x = valueP2X;
double y = valueP2Y;
if (valueAngle == 90 || valueAngle == 270) {
x = x - tickLabelBounds.getWidth() / 2;
}
else if (valueAngle < 90 || valueAngle > 270) {
x = x - tickLabelBounds.getWidth();
}
if ((valueAngle > 135 && valueAngle < 225)
|| valueAngle > 315 || valueAngle < 45) {
y = y - tickLabelBounds.getHeight() / 2;
}
else {
y = y + tickLabelBounds.getHeight() / 2;
}
g2.drawString(tickLabel, (float) x, (float) y);
}
}
/**
* Draws the value label just below the center of the dial.
*
* @param g2 the graphics device.
* @param area the plot area.
*/
protected void drawValueLabel(Graphics2D g2, Rectangle2D area) {
g2.setFont(this.valueFont);
g2.setPaint(this.valuePaint);
String valueStr = "No value";
if (this.dataset != null) {
Number n = this.dataset.getValue();
if (n != null) {
valueStr = this.tickLabelFormat.format(n.doubleValue()) + " "
+ this.units;
}
}
float x = (float) area.getCenterX();
float y = (float) area.getCenterY() + DEFAULT_CIRCLE_SIZE;
TextUtilities.drawAlignedString(valueStr, g2, x, y,
TextAnchor.TOP_CENTER);
}
/**
* Returns a short string describing the type of plot.
*
* @return A string describing the type of plot.
*/
public String getPlotType() {
return localizationResources.getString("Meter_Plot");
}
/**
* A zoom method that does nothing. Plots are required to support the
* zoom operation. In the case of a meter plot, it doesn't make sense to
* zoom in or out, so the method is empty.
*
* @param percent The zoom percentage.
*/
public void zoom(double percent) {
// intentionally blank
}
/**
* Tests the plot for equality with an arbitrary object. Note that the
* dataset is ignored for the purposes of testing equality.
*
* @param obj the object (<code>null</code> permitted).
*
* @return A boolean.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof MeterPlot)) {
return false;
}
if (!super.equals(obj)) {
return false;
}
MeterPlot that = (MeterPlot) obj;
if (!ObjectUtilities.equal(this.units, that.units)) {
return false;
}
if (!ObjectUtilities.equal(this.range, that.range)) {
return false;
}
if (!ObjectUtilities.equal(this.intervals, that.intervals)) {
return false;
}
if (!PaintUtilities.equal(this.dialOutlinePaint,
that.dialOutlinePaint)) {
return false;
}
if (this.shape != that.shape) {
return false;
}
if (!PaintUtilities.equal(this.dialBackgroundPaint,
that.dialBackgroundPaint)) {
return false;
}
if (!PaintUtilities.equal(this.needlePaint, that.needlePaint)) {
return false;
}
if (!ObjectUtilities.equal(this.valueFont, that.valueFont)) {
return false;
}
if (!PaintUtilities.equal(this.valuePaint, that.valuePaint)) {
return false;
}
if (!PaintUtilities.equal(this.tickPaint, that.tickPaint)) {
return false;
}
if (this.tickSize != that.tickSize) {
return false;
}
if (this.tickLabelsVisible != that.tickLabelsVisible) {
return false;
}
if (!ObjectUtilities.equal(this.tickLabelFont, that.tickLabelFont)) {
return false;
}
if (!PaintUtilities.equal(this.tickLabelPaint, that.tickLabelPaint)) {
return false;
}
if (!ObjectUtilities.equal(this.tickLabelFormat,
that.tickLabelFormat)) {
return false;
}
if (this.drawBorder != that.drawBorder) {
return false;
}
if (this.meterAngle != that.meterAngle) {
return false;
}
return true;
}
/**
* Provides serialization support.
*
* @param stream the output stream.
*
* @throws IOException if there is an I/O error.
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
SerialUtilities.writePaint(this.dialBackgroundPaint, stream);
SerialUtilities.writePaint(this.needlePaint, stream);
SerialUtilities.writePaint(this.valuePaint, stream);
SerialUtilities.writePaint(this.tickPaint, stream);
SerialUtilities.writePaint(this.tickLabelPaint, stream);
}
/**
* Provides serialization support.
*
* @param stream the input stream.
*
* @throws IOException if there is an I/O error.
* @throws ClassNotFoundException if there is a classpath problem.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
this.dialBackgroundPaint = SerialUtilities.readPaint(stream);
this.needlePaint = SerialUtilities.readPaint(stream);
this.valuePaint = SerialUtilities.readPaint(stream);
this.tickPaint = SerialUtilities.readPaint(stream);
this.tickLabelPaint = SerialUtilities.readPaint(stream);
if (this.dataset != null) {
this.dataset.addChangeListener(this);
}
}
/**
* Returns an independent copy (clone) of the plot. The dataset is NOT
* cloned - both the original and the clone will have a reference to the
* same dataset.
*
* @return A clone.
*
* @throws CloneNotSupportedException if some component of the plot cannot
* be cloned.
*/
public Object clone() throws CloneNotSupportedException {
MeterPlot clone = (MeterPlot) super.clone();
clone.tickLabelFormat = (NumberFormat) this.tickLabelFormat.clone();
// the following relies on the fact that the intervals are immutable
clone.intervals = new java.util.ArrayList(this.intervals);
if (clone.dataset != null) {
clone.dataset.addChangeListener(clone);
}
return clone;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -