import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.text.*; /** * Meter is a class for drawing Meter. */ public class TransparentMeter extends java.awt.Component implements java.io.Serializable { /** * Image for double buffering. */ transient protected BufferedImage image = null; /** * graphics that is created by double buffering Image. */ transient protected Graphics2D graphics = null; /** * Width of Meter. */ protected int width = 100; /** * Height of Meter. */ protected int height = 100; /** * If dimensional size of Meter is changed, this flag set true. */ protected boolean sizeChangeFlag = false; /** * X coordinate of Meter Center. * It depends on size and shape of Meter */ protected int centerX; /** * X coordinate of Meter Center. * It depends on size and shape of Meter */ protected int centerY; /** * Radius of Meter Hand. * It depends on size and shape of Meter */ protected double radius; /** * Minimum value. */ protected double minimum = 0.0; /** * Maximum value. */ protected double maximum = 1.0; /** * Number that is used for transforming number to angle. */ protected double div; /** * Array for drawing Hand. */ protected int[] xPoints; /** * Array for drawing Hand. */ protected int[] yPoints; /** * Angle corresponding to minimum value. */ protected double minimumAngle = 5.0/6.0 * Math.PI; // 150 degree /** * Angle corresponding to maximum value. */ protected double maximumAngle = 1.0/6.0 * Math.PI; // 30 degree /** * Value. * Meter draw this value. */ protected double value = 0.0; /** * Font metrics. * It is used for drawing the graduation. */ FontMetrics metrics; /** * Number formatter. * It is used for drawing the graduation. */ protected NumberFormat nf; /** * Color of the graduation. */ protected Color gradColor; protected Color transColor = new Color(255, 255, 255, 0); /** * Constructor. * Configurating dimension, color and formatter. */ public TransparentMeter() { div = (maximumAngle - minimumAngle)/(maximum - minimum); xPoints = new int[3]; yPoints = new int[3]; setForeground(Color.yellow); setBackground(Color.black); gradColor = Color.white; decideCenter(); nf = NumberFormat.getInstance(); enableEvents(AWTEvent.COMPONENT_EVENT_MASK); } public Dimension getPreferredSize(){ return new Dimension(100, 100); } public Dimension getMinimumSize(){ return new Dimension(50, 50); } public void processComponentEvent(ComponentEvent e){ if(e.getID() == ComponentEvent.COMPONENT_RESIZED){ Dimension size = getSize(); changeSize(size.width, size.height); } super.processComponentEvent(e); } /** * If Meter size is changed, this routin is called. * Calculating dimension, center and radius again. * * @param width Width of Meter. * @param height Height of Meter. */ protected void changeSize(int width, int height){ System.out.println("ChangeSize " + width + " " + height); this.width = width; this.height = height; decideCenter(); sizeChangeFlag = true; } private void decideCenter(){ if(width > 2 * height){ radius = height * 0.7; }else if(width > height){ radius = width/2.0 * 0.7; }else{ radius = width/2.0 * 0.8; } centerX = width / 2; centerY = (int)(height/2.0 + radius/2.0); } public void setGraduationColor(Color color){ gradColor = color; } public Color getGraduationColor(){ return gradColor; } public void setRange(double minimum, double maximum){ this.minimum = minimum; this.maximum = maximum; div = (maximumAngle - minimumAngle)/(maximum - minimum); } public void setMinimum(double minmum){ this.minimum = minmum; div = (maximumAngle - minimumAngle)/(maximum - minimum); } public double getMinimum(){ return minimum; } public void setMaximum(double maximum){ this.maximum = maximum; div = (maximumAngle - minimumAngle)/(maximum - minimum); } public double getMaximum(){ return maximum; } public void setValue(double value){ this.value = value; repaint(); } protected void drawGraduation(Graphics2D g){ int fontHeight = metrics.getAscent(); int fontWidth; int xoffset, yoffset; double angle; String number; g.setColor(gradColor); g.drawArc((int)(centerX-radius), (int)(centerY-radius), (int)(2*radius), (int)(2*radius), (int)(minimumAngle/Math.PI*180.0), (int)((maximumAngle - minimumAngle)/Math.PI*180.0)); fontWidth = metrics.stringWidth(nf.format(minimum)); angle = minimumAngle; while(angle < 0){ angle += (2.0 * Math.PI); } while(angle > 2.0 * Math.PI){ angle -= (2.0 * Math.PI); } if(angle <= Math.PI/2.0){ xoffset = 0; yoffset = 0; }else if(angle <= Math.PI){ xoffset = -fontWidth; yoffset = 0; }else if(angle <= Math.PI*1.5){ xoffset = -fontWidth; yoffset = fontHeight; }else{ xoffset = 0; yoffset = fontHeight; } g.drawString(nf.format(minimum), centerX + (int)(1.02*radius*Math.cos(minimumAngle)) + xoffset, centerY - (int)(1.02*radius*Math.sin(minimumAngle)) + yoffset); fontWidth = metrics.stringWidth(nf.format(maximum)); angle = maximumAngle; while(angle < 0){ angle += (2.0 * Math.PI); } while(angle > 2.0 * Math.PI){ angle -= (2.0 * Math.PI); } if(angle <= Math.PI/2.0){ xoffset = 0; yoffset = 0; }else if(angle <= Math.PI){ xoffset = -fontWidth; yoffset = 0; }else if(angle <= Math.PI*1.5){ xoffset = -fontWidth; yoffset = fontHeight; }else{ xoffset = 0; yoffset = fontHeight; } g.drawString(nf.format(maximum).toString(), centerX + (int)(1.02*radius*Math.cos(maximumAngle)) + xoffset, centerY - (int)(1.02*radius*Math.sin(maximumAngle)) + yoffset); angle = (maximumAngle + minimumAngle)/2.0; number = nf.format((maximum + minimum)/2.0); fontWidth = metrics.stringWidth(number); while(angle < 0){ angle += (2.0 * Math.PI); } while(angle > 2.0 * Math.PI){ angle -= (2.0 * Math.PI); } if(angle <= Math.PI/2.0){ xoffset = 0; yoffset = 0; }else if(angle <= Math.PI){ xoffset = -fontWidth; yoffset = 0; }else if(angle <= Math.PI*1.5){ xoffset = -fontWidth; yoffset = fontHeight; }else{ xoffset = 0; yoffset = fontHeight; } g.drawString(number, centerX + (int)(1.02*radius*Math.cos(angle)) + xoffset, centerY - (int)(1.02*radius*Math.sin(angle)) + yoffset); if(minimumAngle < maximumAngle){ int i; for(i = 0, angle = minimumAngle ; i < 5 ; i++, angle += (maximumAngle - minimumAngle)/4.0){ g.drawLine(centerX + (int)(radius*Math.cos(angle)), centerY - (int)(radius*Math.sin(angle)), centerX + (int)(0.95*radius*Math.cos(angle)), centerY - (int)(0.95*radius*Math.sin(angle))); } }else{ int i; for(i = 0, angle = maximumAngle ; i < 5 ; i++, angle += (minimumAngle - maximumAngle)/4.0){ g.drawLine(centerX + (int)(radius*Math.cos(angle)), centerY - (int)(radius*Math.sin(angle)), centerX + (int)(0.95*radius*Math.cos(angle)), centerY - (int)(0.95*radius*Math.sin(angle))); } } } protected void drawHand(Graphics2D g, double value){ if(value > maximum + (maximum - minimum) * 0.05){ value = maximum + (maximum - minimum) * 0.05; }else if(value < minimum - (maximum - minimum) * 0.05){ value = minimum - (maximum - minimum) * 0.05; } xPoints[0] = (int)(centerX + radius*Math.cos(minimumAngle + div * (value-minimum))); yPoints[0] = (int)(centerY - radius*Math.sin(minimumAngle + div * (value-minimum))); xPoints[1] = (int)(centerX + radius/20.0*Math.cos(minimumAngle + div * value + Math.PI/2.0)); yPoints[1] = (int)(centerY - radius/20.0*Math.sin(minimumAngle + div * value + Math.PI/2.0)); xPoints[2] = (int)(centerX + radius/20*Math.cos(minimumAngle + div * value - Math.PI/2.0)); yPoints[2] = (int)(centerY - radius/20.0*Math.sin(minimumAngle + div * value - Math.PI/2.0)); g.setColor(getForeground()); g.drawPolygon(xPoints, yPoints, 3); g.fillPolygon(xPoints, yPoints, 3); } public void update(Graphics g){ paint(g); } public void paint(Graphics g){ if(image == null){ System.out.println(width + " " + height); Dimension size = getSize(); changeSize(size.width, size.height); image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_4BYTE_ABGR); graphics = (Graphics2D)image.getGraphics(); metrics = Toolkit.getDefaultToolkit().getFontMetrics(getFont()); }else if(sizeChangeFlag){ Dimension size = getSize(); image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_4BYTE_ABGR); graphics = (Graphics2D)image.getGraphics(); sizeChangeFlag = false; } graphics.setBackground(transColor); graphics.clearRect(0, 0, width, height); drawGraduation(graphics); drawHand(graphics, value); g.drawImage(image, 0, 0, width, height, this); } }