您的位置:首页 > 其它

分享超轻量Swing仪表盘组件(带源码)

2012-06-11 18:44 134 查看
http://www.iteye.com/topic/1123249

XDoc发布了8.2.5版本,新版本中增加了扩展组件:刻度盘,用于动态图示化展示数据

现在将它封装成一个Swing组件与大家分享,大家可以稍做调整画出更漂亮的仪表盘

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* 刻度盘
* @author xdoc
*/
public class Tick extends JComponent {
private static final int VALUE_FONT_SIZE = 18;
private double from = 0;
private double to = 10;
private String type = "line";
private double major = 1;
private double minor = 0.1;
private String value = "";
private String unit = "";
public double getFrom() {
return from;
}
public Tick() {
super();
this.setPreferredSize(new Dimension(60, 60));
this.setBackground(Color.WHITE);
}
public void setFrom(double from) {
this.from = from;
}
public double getMajor() {
return major;
}
public void setMajor(double major) {
this.major = major;
}
public double getMinor() {
return minor;
}
public void setMinor(double minor) {
this.minor = minor;
}
public double getTo() {
return to;
}
public void setTo(double to) {
this.to = to;
}
public String getType() {
return type;
}
/**
* 直尺
*/
public static final String LINE = "line";
/**
* 120度圆环
*/
public static final String RING_120 = "ring120";
public static final String RING_180 = "ring180";
public static final String RING_240 = "ring240";
/**
* 圆盘
*/
public static final String CIRCLE = "circle";
public void setType(String type) {
this.type = type;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public void paintComponent(Graphics g) {
double w = this.getWidth();
double h = this.getHeight();
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(this.getBackground());
g2.fillRect(0, 0, (int) w, (int) h);
g2.setColor(this.getForeground());
g2.setStroke(new BasicStroke(1));
int fontSize = 14;
g2.setFont(new Font(Font.SERIF, Font.PLAIN, fontSize));
if (major <= 0) {
major = to - from;
}
if (to > from) {
if (type.startsWith("ring") || type.equals("circle")) {
double angle;
double angleStart;
if (type.equals("circle")) {
angle = 360;
angleStart = Math.PI / 2;
} else {
angle = toDouble(type.substring(4));
angleStart = (180 + (angle - 180) / 2) / 180 * Math.PI;
}
double r = angle <= 180 ? Math.min(w / 2, h) : Math.min(w / 2, h / 2);
double voff = angle <= 180 ? 0 : r;
double dunit = (angle / 180 * Math.PI) / (to - from);
for (int i = 0; i <= (to - from) / major; i++) {
g2.draw(new Line2D.Double(Math.cos(angleStart - i * major * dunit) * r + w / 2, h - voff - Math.sin(angleStart - i * major * dunit) * r,
Math.cos(angleStart - i * major * dunit) * r * 0.75 + w / 2, h - voff - Math.sin(angleStart - i * major * dunit) * r * 0.75));
if (minor > 0 && i < (to - from) / major) {
for (int j = 1; j < major / minor; j++) {
if (i * major + j * minor < to - from) {
g2.draw(new Line2D.Double(Math.cos(angleStart - (i * major + j * minor) * dunit) * r + w / 2, h - voff - Math.sin(angleStart - (i * major + j * minor) * dunit) * r,
Math.cos(angleStart - (i * major + j * minor) * dunit) * r * 0.875 + w / 2, h - voff - Math.sin(angleStart - (i * major + j * minor) * dunit) * r * 0.875));
}
}
}
}
if (value.length() > 0) {
double val = toDouble(value);
GeneralPath p = new GeneralPath();
p.moveTo(Math.cos(angleStart - (val - from) * dunit) * r * 0.875 + w / 2, h - voff - Math.sin(angleStart - (val - from) * dunit) * r * 0.875);
p.lineTo(Math.cos(angleStart - (val - from) * dunit + Math.PI * 0.5) * 2 + w / 2, h - voff - Math.sin(angleStart - (val - from) * dunit + Math.PI * 0.5) * 2);
p.lineTo(Math.cos(angleStart - (val - from) * dunit - Math.PI * 0.5) * 2 + w / 2, h - voff - Math.sin(angleStart - (val - from) * dunit - Math.PI * 0.5) * 2);
p.closePath();
g2.fill(p);
}
} else {
if (w > h) {
double dunit = w / (to - from);
for (int i = 0; i <= (to - from) / major; i++) {
g2.draw(new Line2D.Double(i * major * dunit, 0, i * major * dunit, h - fontSize));
if (i < (to - from) / major && minor > 0) {
for (int j = 1; j < major / minor; j++) {
g2.draw(new Line2D.Double((i * major + j * minor) * dunit, 0, (i * major + j * minor) * dunit, (h - fontSize) / 2));
}
}
}
if (value.length() > 0) {
double val = toDouble(value);
GeneralPath p = new GeneralPath();
p.moveTo((val - from) * dunit, (h - fontSize) / 2);
p.lineTo((val - from) * dunit - 4, h - fontSize);
p.lineTo((val - from) * dunit + 4, h - fontSize);
p.closePath();
g2.fill(p);
}
} else {
int max = (int) Math.max(getStrBounds(g2, format(from)).getWidth(), getStrBounds(g2, format(to)).getWidth());
double dunit = h / (to - from);
for (int i = 0; i <= (to - from) / major; i++) {
g2.draw(new Line2D.Double(0, h - i * major * dunit, w - max, h - i * major * dunit));
if (i < (to - from) / major && minor > 0) {
for (int j = 1; j < major / minor; j++) {
g2.draw(new Line2D.Double(0, h - (i * major + j * minor) * dunit, (w - max) / 2, h - (i * major + j * minor) * dunit));
}
}
}
if (value.length() > 0) {
double val = toDouble(value);
GeneralPath p = new GeneralPath();
p.moveTo((w - max) / 2, h - (val - from) * dunit);
p.lineTo(w - max, h - (val - from) * dunit - 4);
p.lineTo(w - max, h - (val - from) * dunit + 4);
p.closePath();
g2.fill(p);
}
}
}
}
if (to > from) {
if (major > 0) {
if (type.startsWith("ring") || type.equals("circle")) {
double angle;
double angleStart;
if (type.equals("circle")) {
angle = 360;
angleStart = Math.PI / 2;
} else {
angle = toDouble(type.substring(4));
angleStart = (180 + (angle - 180) / 2) / 180 * Math.PI;
}
double r = angle <= 180 ? Math.min(w / 2, h) : Math.min(w / 2, h / 2);
double voff = angle <= 180 ? 0 : r;
double dunit = (angle / 180 * Math.PI) / (to - from);
int xoff = 0;
int yoff = 0;
double strAngle;
for (int i = type.equals("circle") ? 1 : 0; i <= (to - from) / major; i++) {
String str;
str = format(from + i * major);
strAngle = (angleStart - i * major * dunit + Math.PI * 2) % (Math.PI * 2);
xoff = 0;
yoff = 0;
if (strAngle >= 0 && strAngle < Math.PI * 0.25) {
xoff = (int) -getStrBounds(g2, str).getWidth();
yoff = fontSize / 2;
if (strAngle == 0 && angle == 180) {
yoff = 0;
}
} else if (near(strAngle, Math.PI * 0.5)) {
xoff = (int) -getStrBounds(g2, str).getWidth() / 2;
yoff = fontSize;
} else if (strAngle >= Math.PI * 0.25 && strAngle < Math.PI * 0.5) {
xoff = (int) -getStrBounds(g2, str).getWidth();
yoff = fontSize;
} else if (strAngle >= Math.PI * 0.5 && strAngle < Math.PI * 0.75) {
yoff = fontSize;
} else if (strAngle >= Math.PI * 0.75 && strAngle < Math.PI) {
yoff = fontSize / 2;
} else if (near(strAngle, Math.PI)) {
xoff = 1;
yoff = fontSize / 2;
if (angle == 180) {
yoff = 0;
}
} else if (strAngle >= Math.PI && strAngle < Math.PI * 1.25) {
yoff = fontSize / 4;
} else if (near(strAngle, Math.PI * 1.5)) {
xoff = (int) -getStrBounds(g2, str).getWidth() / 2;
} else if (strAngle >= Math.PI * 1.5 && strAngle < Math.PI * 2) {
xoff = (int) -getStrBounds(g2, str).getWidth();
}
g2.drawString(str, (int) (Math.cos(strAngle) * r * 0.75 + w / 2) + xoff, (int) (h - voff - Math.sin(strAngle) * r * 0.75) + yoff);
}
g2.setFont(new Font("", Font.BOLD, VALUE_FONT_SIZE));
if (value.length() > 0) {
voff = angle <= 180 ? 10 : r - fontSize / 2;
drawValue(g2, value + unit, (int) (w / 2 - getStrBounds(g2, value).getWidth() / 2), (int) (h - voff));
}
} else {
if (w > h) {
double dunit = w / (to - from);
int off = 0;
String str;
for (int i = 0; i <= (to - from) / major; i++) {
str = format(from + i * major);
if (i == 0) {
str += unit;
off = 0;
} else if (i == (to - from) / major) {
off = (int) -getStrBounds(g2, str).getWidth();
} else {
off = (int) (-getStrBounds(g2, str).getWidth() / 2);
}
g2.drawString(str, (int) (i * major * dunit) + off, (int) (h - 2));
}
if (value.length() > 0) {
double val = toDouble(value);
value = format(val);
if (val == from) {
off = 0;
} else if (val == to) {
off = (int) -getStrBounds(g2, value + unit).getWidth();
} else {
off = (int) (-getStrBounds(g2, value + unit).getWidth() / 2);
}
if ((h - fontSize) / 2 >= fontSize) {
drawValue(g2, value + unit, (int) ((val - from) * dunit) + off, (int) ((h - fontSize) / 2));
} else {
drawValue(g2, value + unit, (int) ((val - from) * dunit) + off, fontSize);
}
}
} else {
double dunit = h / (to - from);
int max = (int) Math.max(getStrBounds(g2, format(from)).getWidth(), getStrBounds(g2, format(to)).getWidth());
int off = 0;
for (int i = 0; i <= (to - from) / major; i++) {
if (i == 0) {
off = 0;
} else if (i == (to - from) / major) {
off = fontSize;
} else {
off = fontSize / 2;
}
g2.drawString(format(from + i * major), (int) (w - max + 1), (int) (h - i * major * dunit) + off);
}
if (unit.length() > 0) {
g2.drawString(unit, (int) ((w - max) / 2 + 1), (int) (h - fontSize));
}
if (value.length() > 0) {
double val = toDouble(value);
value = format(val);
if (val == 0) {
off = 0;
} else if (val == to) {
off = VALUE_FONT_SIZE;
} else {
off = VALUE_FONT_SIZE / 2;
}
drawValue(g2, value + unit, (int) ((w - getStrBounds(g2, value + unit).getWidth()) / 2), (int) (h - (val - from) * dunit + off));
}
}
}
}
}
}
private void drawValue(Graphics2D g2, String value, int x, int y) {
g2.setFont(new Font(Font.SERIF, Font.BOLD, VALUE_FONT_SIZE));
g2.drawString(value, x, y);
}
private String format(double d) {
if ((int) d == d) {
return String.valueOf((int) d);
} else {
return String.valueOf(d);
}
}
private double toDouble(String string) {
try {
return Double.valueOf(string);
} catch (Exception e) {
return 0;
}
}
private boolean near(double d1, double d2) {
return Math.round(d1 * 1000000) == Math.round(d2 * 1000000);
}
private static Rectangle2D getStrBounds(Graphics2D g, String str) {
Font f = g.getFont();
Rectangle2D rect = f.getStringBounds(str, g.getFontRenderContext());
if (rect.getHeight() < f.getSize()) {
rect.setFrame(rect.getX(), rect.getY(), rect.getWidth(), f.getSize() + 1);
}
return rect;
}
public static void main(String[] args) {
try {
JFrame f = new JFrame("刻度盘测试");
Container p = f.getContentPane();
Tick tick;
tick = new Tick();
tick.setType(Tick.LINE);
tick.setValue("3");
tick.setUnit("CM");
p.add(tick, BorderLayout.NORTH);
tick = new Tick();
tick.setType(Tick.LINE);
p.add(tick, BorderLayout.WEST);
JPanel panel = new JPanel(new GridLayout(2, 2));
tick = new Tick();
tick.setForeground(Color.BLUE);
tick.setType(Tick.RING_120);
tick.setValue("3.5");
tick.setUnit("A");
panel.add(tick);
tick = new Tick();
tick.setType(Tick.RING_180);
tick.setValue("6");
tick.setUnit("V");
panel.add(tick);
tick = new Tick();
tick.setType(Tick.RING_240);
tick.setValue("3");
tick.setUnit("Kg");
panel.add(tick);
tick = new Tick();
tick.setType(Tick.CIRCLE);
tick.setValue("3");
tick.setUnit("Kg");
tick.setBackground(Color.BLACK);
tick.setForeground(Color.WHITE);
panel.add(tick);
p.add(panel, BorderLayout.CENTER);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(640, 480);
f.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: