java实现渐变效果工具

java实现渐变效果工具

java实现渐变效果工具

java实现渐变效果工具

java实现渐变效果工具

java实现渐变效果工具

java实现渐变效果工具

[html] view plain copy
package gradient;  

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.LinearGradientPaint;
import java.awt.MultipleGradientPaint;
import java.awt.Paint;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List; import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; /*
使用方法:
渐变窗体:
a. 左键双击顶点的linear gradient 渐变区,改变渐变超出范围的重复绘制模式.
b. 左键双击fractions小按钮区,创建添加一个新的fraction按钮.
c. 左键双击fractions小按钮,弹出窗口选择窗口选择颜色.
d. 右键双击fractions小按钮,删除此fraction按钮.
e. 按住fractions小按钮可以拖动它,修改fractions的位置.
f. 左键双击辐射渐变区,改变辐射渐变的焦点(focus)到点击位置.
g. 在辐射渐变区按住左键拖动,改变辐射渐变的焦点.
h. 按下f,显示辐射渐变的圆周,为了方便看到更清楚的数据,默认这圆周是隐藏的.
i. 按下c,恢复辐射渐变的焦点到辐射渐变的圆心,焦点默认是与圆心重合. 颜色选择窗体:
a. 单击某一个颜色,则选中此颜色,并在底部的预览区显示出来.但颜色选择窗口不消失.
b. 双击某一个颜色,则选中此颜色,返回给调用者,颜色选择窗口消失.
c. 按下回车键,返回选中的颜色,颜色选择窗口消失.
d. 按下ESC键,返回传给颜色选择窗体的默认色,颜色选择窗口消失.
e. 下部的JSlider依次调节被选中颜色的red, green, blue, alpha,拖动并实时的在预览区显示出调整后颜色. 第三方程序集成使用方法: 在第三方程序中创建一个GradientGenerator对象,并添加到组件的某一部分,
并给此gradientGenerator添加上change listener:
gradientGenerator.addChangeListener(new ChangedListener() {
public void stateChanged(ChangeEvent e) {
float[] fractions = gradientGenerator.getFractons();
Color[] colors = gradientGenerator.getColors();
Point2D focus = gradientGenerator.calculateFocus(center, radius);
repaint(); // 使用这里得到的fractions, colors, focus等去绘制第三方程序中的渐变图形
});
这样,当gradient generator中的数据发生变化时,第三方程序里也会即时的反映出来. 1. 提示,现在Swing支持合建不规则窗体。
2. 此程序中,除了JSlider,其他的部分都是使用Java2D手动计算绘制出来的。
基于上面两点,可以自己创建一个统一的JSlider风格,
然后就可以把整个程序的外观风格做得在所有平台下都是一个样。
*/
/**
* *^o^*,本程序一惯还是一惯的作风,LGPL协议,什么版权的废话就不整了,希望修改得效果好的朋友给大家分享一下心得,在此权当扔出块板砖,
* 希望能砸出块暖玉来,嗷呜嗷呜嗷呜.
*/
@SuppressWarnings("serial")
public class GradientGenerator extends JPanel {
private int width = 400; // 整个Panel的宽度
private int height = 400; // 整个Panel的高度
private Insets padding = new Insets(10, 10, 10, 10); // 边距 private int thumbRectHeight = 20; // Fraction按钮区的高度
private int linearRectHeight = 40; // 线性渐变区域的高度
private int radialRectHeight = 310; // 辐射渐变区域的高度 private Ellipse2D radialCircle = new Ellipse2D.Float(); // 辐射渐变的圆周
private Point2D focusPoint = new Point2D.Float(); // 辐射渐变的焦点
private Point2D pressedPoint = new Point2D.Float(); // 鼠标按下时的点
private Rectangle2D linearRect = new Rectangle2D.Float(); // 线性渐变区域
private Rectangle2D thumbsRect = new Rectangle2D.Float(); // Fractions按钮区域
private Rectangle2D radialRect = new Rectangle2D.Float(); // 辐射渐变区域 private Thumb selectedThumb = null; // 被选中的Fraction按钮
private List<Thumb> thumbs = new ArrayList<Thumb>(); // Fractions按钮 private boolean showCircle = false; // 显示辐射渐变的圆周
private List<ChangeListener> changeListeners = new LinkedList<ChangeListener>();
private MultipleGradientPaint.CycleMethod cycleMethod = MultipleGradientPaint.CycleMethod.REFLECT; /**
* 返回渐变的fractions数组
*
* @return
*/
public float[] getGradientFractions() {
float[] fractions = new float[thumbs.size()];
int i = 0;
for (Thumb t : thumbs) {
fractions[i] = (float) ((t.getX() - padding.left) / linearRect.getWidth());
++i;
}
return fractions;
} /**
* 返回渐变的colors数组
*
* @return
*/
public Color[] getGradientColors() {
Color[] colors = new Color[thumbs.size()];
int i = 0;
for (Thumb t : thumbs) {
colors[i] = t.getColor();
++i;
} return colors;
} /**
* 利用指定圆的圆心和半径和当前的辐射渐变数据,计算相对于指定圆的焦点
*
* @param center
* 圆心
* @param radius
* 半径
* @return 返回相对于指定圆的焦点
*/
public Point2D calculateFocus(Point2D center, double radius) {
Point2D curCenter = new Point2D.Double(radialCircle.getCenterX(), radialCircle.getCenterY());
double curRadius = radialCircle.getWidth() / 2;
double curFocusLen = GeometryUtil.distanceOfPoints(curCenter, focusPoint); double newFocusLen = radius * curFocusLen / curRadius;
Point2D newFocusPoint = GeometryUtil.extentPoint(curCenter, focusPoint, newFocusLen);
// 先移回原点,再移动到center的位置
newFocusPoint.setLocation(center.getX() - curCenter.getX(),
center.getY() - curCenter.getY()); return newFocusPoint;
} public GradientGenerator() {
setFocusable(true); // 为了能接收键盘按键事件
afterResized();
resetThumbs(new float[] { 0.0f, 0.5f, 1.0f }, new Color[] { Color.BLACK, Color.BLUE,
new Color(255, 255, 255, 220) });
handleEvents(); setBackground(Color.DARK_GRAY);
} // 事件处理
private void handleEvents() {
this.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
pressedPoint.setLocation(x, y); // 得到被选中的Thumb
for (Thumb t : thumbs) {
if (t.contains(x, y)) {
t.setSelected(true);
selectedThumb = t;
break;
}
}
repaint();
} @Override
public void mouseReleased(MouseEvent e) {
for (Thumb t : thumbs) {
t.setSelected(false);
selectedThumb = null;
}
repaint();
} @Override
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
// 左键双击
if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
// 如果在thumbs里面,则弹出颜色选择器
for (Thumb t : thumbs) {
if (t.contains(x, y)) {
changeThumbColor(t);
repaint();
return;
}
} // 如果不在thumbs里,而在thumbs的区域里,则增加一个thumb
if (thumbsRect.contains(x, y)) {
insertThumbAt(x);
repaint();
return;
} // 修改focus的位置
if (radialRect.contains(x, y)) {
changeFocusPoint(new Point2D.Float(x, y));
repaint();
return;
} // 在Linear rect里面,修改cycle method
if (linearRect.contains(x, y)) {
changeCycleMethod();
repaint();
return;
}
} else if (e.getButton() == MouseEvent.BUTTON3 && e.getClickCount() == 2) {
// 右键双击
removeThumbAt(x, y);
return;
}
}
}); this.addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
// 拖动滑块
if (selectedThumb != null) {
int deltaX = e.getX() - (int) (selectedThumb.getX());
int x = selectedThumb.getX() + deltaX; // 不能超过边界
int maxRight = (int) (padding.left + linearRect.getWidth());
if (x < padding.left || x > maxRight) { return; } int index = thumbs.indexOf(selectedThumb);
int prevX = Integer.MIN_VALUE;
int nextX = Integer.MAX_VALUE;
// 只能在前一个和后一个之间移动
if (index - 1 >= 0) {
prevX = (int) (thumbs.get(index - 1).getX());
} if (index + 1 < thumbs.size()) {
nextX = (int) (thumbs.get(index + 1).getX());
} if (x > prevX && x < nextX) {
selectedThumb.setX(x);
repaint();
}
return;
} else if (radialRect.contains(e.getX(), e.getY())) {
int deltaX = (int) (e.getX() - pressedPoint.getX());
int deltaY = (int) (e.getY() - pressedPoint.getY());
focusPoint.setLocation(focusPoint.getX() + deltaX, focusPoint.getY() + deltaY);
pressedPoint.setLocation(e.getX(), e.getY());
repaint();
} }
}); this.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_F:
showCircle = !showCircle;
break;
case KeyEvent.VK_C:
changeFocusPoint(radialCircle.getCenterX(), radialCircle.getCenterY());
break;
}
repaint();
}
});
} // 执行监听器的事件
public void fireChangeEvent() {
for (ChangeListener l : changeListeners) {
l.stateChanged(new ChangeEvent(this));
}
} // 改变超出渐变区的颜色渐变方式
public void changeCycleMethod() {
changeCycleMethod(cycleMethod);
} public void changeCycleMethod(MultipleGradientPaint.CycleMethod cycleMethod) {
switch (cycleMethod) {
case NO_CYCLE:
this.cycleMethod = MultipleGradientPaint.CycleMethod.REFLECT;
break;
case REFLECT:
this.cycleMethod = MultipleGradientPaint.CycleMethod.REPEAT;
break;
case REPEAT:
this.cycleMethod = MultipleGradientPaint.CycleMethod.NO_CYCLE;
break;
}
} @Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); drawLinearRect(g2d);
drawThumbsRect(g2d);
drawRadialRect(g2d);
} // 绘制fraction按钮所在区域
private void drawThumbsRect(Graphics2D g2d) {
g2d.setColor(new Color(255, 255, 255, 40));
g2d.fill(thumbsRect); // 绘制fraction按钮
for (Thumb t : thumbs) {
t.paint(g2d);
}
} private void drawLinearRect(Graphics2D g2d) {
// 绘制线性渐变区域
float sx = (float) linearRect.getX();
float sy = (float) linearRect.getY();
float ex = (int) (sx + linearRect.getWidth());
float ey = sy;
float[] fractions = getGradientFractions();
Color[] colors = getGradientColors();
Paint p = new LinearGradientPaint(sx, sy, ex, ey, fractions, colors, cycleMethod); TransparentPainter.paint(g2d, linearRect);
g2d.setPaint(p);
g2d.fill(linearRect);
} // 绘制辐射渐变区
private void drawRadialRect(Graphics2D g2d) {
float cx = (float) radialCircle.getCenterX();
float cy = (float) radialCircle.getCenterY();
float fx = (float) focusPoint.getX();
float fy = (float) focusPoint.getY();
float radius = (float) radialCircle.getWidth() / 2;
float[] fractions = getGradientFractions();
Color[] colors = getGradientColors(); TransparentPainter.paint(g2d, radialRect); Paint p = new RadialGradientPaint(cx, cy, radius, fx, fy, fractions, colors, cycleMethod);
g2d.setPaint(p);
g2d.fill(radialRect); if (showCircle) {
// 绘制辐射渐变的圆
g2d.setPaint(Color.BLACK);
g2d.draw(radialCircle);
}
} // 最少需要两个渐变值,所以开始就创建两个fraction
public void resetThumbs(float[] fractions, Color[] colors) {
if (fractions == null || colors == null) { throw new NullPointerException(); }
if (fractions.length != colors.length) { throw new IllegalArgumentException(
"Fractions 和 Colors 参数个数不等"); } int x = (int) thumbsRect.getX();
int w = (int) thumbsRect.getWidth();
for (int i = 0; i < fractions.length; ++i) {
insertThumbAt(x + (int) (w * fractions[i]), colors[i]);
}
} // 在指定的水平位置插入Fraction按钮
private void insertThumbAt(int x) {
insertThumbAt(x, Color.BLUE);
} private void insertThumbAt(int x, Color color) {
int index = 0;
for (Thumb t : thumbs) {
if (x > t.getX()) {
index++;
}
} int y = (int) (padding.top + linearRect.getHeight());
thumbs.add(index, new Thumb(x, y, color)); fireChangeEvent();
} public void removeThumbAt(int x, int y) {
for (Thumb t : thumbs) {
if (t.contains(x, y)) {
if (thumbs.size() > 2) {
thumbs.remove(t);
fireChangeEvent();
break;
}
}
}
} private void changeThumbColor(Thumb thumb) {
// 弹出颜色选择器
Color newColor = ColorChooser.chooseColor(this, thumb.getColor());
if (newColor != null) {
thumb.setColor(newColor);
fireChangeEvent();
}
} // 改变焦点的位置
public void changeFocusPoint(double x, double y) {
focusPoint.setLocation(x, y);
fireChangeEvent();
} private void changeFocusPoint(Point2D focusPoint) {
changeFocusPoint(focusPoint.getX(), focusPoint.getY());
} // 当panel的大小改变时,再次调用此函数更新显示区域
private void afterResized() {
// ////////////////////////////////////////
// padding-top
// linear gradient area
// thumbs area
// padding = padding top
// radial gradient area
// padding-bottom
// /////////////////////////////////////// // 线性渐变显示区域
int x = padding.left;
int y = padding.top;
int w = width - padding.left - padding.right;
int h = linearRectHeight;
linearRect.setRect(x, y, w, h); // Fraction按钮所在区域
y += linearRectHeight;
h = thumbRectHeight;
thumbsRect.setRect(x, y, w, h); // 辐射渐变显示区域
y = padding.top + linearRectHeight + thumbRectHeight + padding.top;
h = radialRectHeight;
h = Math.min(w, h);
x = (width - w) / 2;
radialRect.setRect(x, y, w, h); // 中心点和焦点
int cx = x + w / 2;
int cy = y + h / 2;
int radius = 100;
focusPoint.setLocation(cx, cy);
radialCircle.setFrame(cx - radius, cy - radius, radius + radius, radius + radius); repaint();
} @Override
public Dimension getMinimumSize() {
return new Dimension(width, height);
} @Override
public Dimension getMaximumSize() {
return new Dimension(width, height);
} @Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
} private static void createGuiAndShow() {
JFrame frame = new JFrame("Gradient Generator");
JPanel panel = new JPanel();
panel.add(new GradientGenerator());
frame.setContentPane(new GradientGenerator()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); // 使用此函数后always on top就不起作用了
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(true);
frame.setVisible(true);
} public static void main(String[] args) {
createGuiAndShow();
}
} class Thumb {
private int x;
private int y;
private int width = 16;
private int height = 20;
private Color color;
private boolean selected; private GeneralPath outerPath;
private GeneralPath innerPath; public Thumb(int x, int y, Color color) {
setXY(x, y);
this.color = color;
} public int getX() {
return x;
} public void setX(int x) {
setXY(x, y);
} public int getY() {
return y;
} public void setY(int y) {
setXY(x, y);
} public int getWidth() {
return width;
} public void setWidth(int width) {
setWidthHeight(width, height);
} public int getHeight() {
return height;
} public void setHeight(int height) {
setWidthHeight(width, height);
} public Color getColor() {
return color;
} public void setColor(Color color) {
this.color = color;
} public boolean isSelected() {
return selected;
} public void setSelected(boolean selected) {
this.selected = selected;
} public boolean contains(int x, int y) {
return outerPath.contains(x, y);
} public void setXY(int x, int y) {
this.x = x;
this.y = y;
createPaths();
} public void setWidthHeight(int width, int height) {
this.width = width;
this.height = height;
createPaths();
} private float[] fractions = new float[] { 0.0f, 0.5f, 1.0f };
private Color[] colors = new Color[] { Color.ORANGE, Color.BLACK, Color.ORANGE.brighter() }; public void paint(Graphics2D g2d) {
// 绘制大三角形按钮
// Paint p = new GradientPaint(x, y, selected ? color.darker() : color,
// x, y + height, Color.ORANGE);
Paint p = new LinearGradientPaint(x - width, y, x + width / 4, y, fractions, colors);
g2d.setPaint(p);
g2d.fill(outerPath); // 绘制小三角形按钮
g2d.setColor(color);
g2d.fill(innerPath);
} // 创建按钮的形状
private void createPaths() {
outerPath = new GeneralPath();
outerPath.moveTo(x, y);
outerPath.lineTo(x + width / 2, y + height);
outerPath.lineTo(x - width / 2, y + height);
outerPath.closePath(); innerPath = new GeneralPath();
innerPath.moveTo(x, y + height / 2);
innerPath.lineTo(x + width / 4, y + height);
innerPath.lineTo(x - width / 4, y + height);
innerPath.closePath();
}
} [html] view plain copy
package gradient; import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner; import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; /**
* 创建一个模态的颜色选择对话框,可以加载用户预先定义存储好的颜色.
*
* @author Biao
*
*/
@SuppressWarnings("serial")
public class ColorChooser extends JDialog {
private static ColorChooser instance = new ColorChooser();
private ColorPanel colorPanel = new ColorPanel();
private Color color; public static Color chooseColor(JComponent ower, Color defaultColor) {
instance.color = defaultColor;
instance.colorPanel.startSelect(defaultColor); instance.pack();
instance.setLocationRelativeTo(ower);
instance.setVisible(true); return instance.color;
} private ColorChooser() {
setTitle("Choose a color");
setModal(true);
setResizable(false);
setBackground(Color.DARK_GRAY);
getContentPane().add(colorPanel, BorderLayout.CENTER); this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
gotoHell(color);
}
}); colorPanel.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
Color c = colorPanel.getColor();
if (colorPanel.isDoubleClickSelection()) {
gotoHell(c);
} int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();
int a = c.getAlpha(); String hex = ColorPanel.colorToHexString(new Color(r, g, b, a));
String title = String.format("RGBA(%d,%d,%d,%d) Hex(%s)", r, g, b, a, hex);
setTitle(title);
}
}); // 处理JDialog所有子组件的按键事件
// 按下回车使用选择的颜色,按下Esc返回默认传进来的颜色
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
KeyEvent ke = (KeyEvent) event; if (ke.getID() == KeyEvent.KEY_PRESSED) {
if (event.getSource() instanceof Component) {
Component com = (Component) event.getSource();
if (ke.getKeyCode() == KeyEvent.VK_ESCAPE && hasChild(com)) {
gotoHell(color); // 取消时返回默认的颜色
} else if (ke.getKeyCode() == KeyEvent.VK_ENTER && hasChild(com)) {
gotoHell(colorPanel.getColor());
}
}
}
}
}, AWTEvent.KEY_EVENT_MASK);
} // 是否包含了组件
public boolean hasChild(Component c) {
for (Component parent = c; parent != null; parent = parent.getParent()) {
if (parent == this) { return true; }
}
return false;
} // 隐藏颜色选择对话框
public void gotoHell(Color c) {
color = (c == null) ? color : c;
setVisible(false);
}
} @SuppressWarnings("serial")
class ColorPanel extends JPanel {
final static private int columnSize = 21; // 每行最多显示21个颜色
final static private int sliderHeight = 20; // Slider的高度
final static private int previewHeight = 20; // 预览区的高度
final static private int colorRectWidth = 20; // 颜色小方块的宽度
final static private int colorRectHeight = 20;// 颜色小方块的高度 private int width = 520; // Color panel的尺寸
private int height = 340;
private Insets padding = new Insets(10, 10, 0, 10); // 边距 private int margin = padding.top;
private Color color = Color.WHITE;
private List<Color> storedColors = new ArrayList<Color>(); // 用户存储的颜色
private List<Color> defaultColors = new ArrayList<Color>(); // 使用算法生成的默认颜色
private Rectangle2D previewRect = new Rectangle2D.Float(); // 预览区域
private Rectangle2D colorsImageRect = new Rectangle2D.Double(); // 显示颜色的区域
private BufferedImage colorsImage; // 需要使用颜色信息来创建确定大小 // 调节rgba的slider
private JSlider redSlider = new JSlider(0, 255, 255);
private JSlider greenSlider = new JSlider(0, 255, 255);
private JSlider blueSlider = new JSlider(0, 255, 255);
private JSlider alphaSlider = new JSlider(0, 255, 255); // 双击时如果选中颜色,则选择完成
private boolean doubleClickSelection = false;
private List<ChangeListener> changeListeners = new ArrayList<ChangeListener>(); public ColorPanel() {
// 创建颜色和显示颜色的小方块缓冲图像
prepareColors();
prepareColorsImage();
// 窗口的大小需要用color buffer image的大小来确定,所以必须在这里调用
prepareSize(); preparePreview();
prepareSliders(); this.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Color c = getColorAt(x, y); if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) {
// 单击时设置选中的颜色
if (c != null) {
setColor(c);
fireStateChanged();
}
} else if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
// 双击时返回选中的颜色,隐藏颜色选取窗口
if (c != null || previewRect.contains(x, y)) {
setDoubleClickSelection(true);
fireStateChanged();
}
}
}
}); redSlider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
setR(redSlider.getValue());
fireStateChanged();
}
}); greenSlider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
setG(greenSlider.getValue());
fireStateChanged();
}
}); blueSlider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
setB(blueSlider.getValue());
fireStateChanged();
}
}); alphaSlider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
setA(alphaSlider.getValue());
fireStateChanged();
}
});
} @Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.DARK_GRAY);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // 绘制颜色方块的缓冲图片
int x = (int) colorsImageRect.getX();
int y = (int) colorsImageRect.getY();
int w = (int) colorsImageRect.getWidth();
int h = (int) colorsImageRect.getHeight();
g2d.drawImage(colorsImage, x, y, w, h, null); // 绘制颜色预览
TransparentPainter.paint(g2d, previewRect);
g2d.setPaint(color);
g2d.fill(previewRect);
} public void startSelect(Color color) {
setColor(color);
setDoubleClickSelection(false);
} public boolean isDoubleClickSelection() {
return doubleClickSelection;
} protected void setDoubleClickSelection(boolean doubleClickSelection) {
this.doubleClickSelection = doubleClickSelection;
} // 当属性改变事件发生时,调用监听器并且重绘
public void fireStateChanged() {
for (ChangeListener l : changeListeners) {
l.stateChanged(new ChangeEvent(this));
}
repaint();
} public void addChangeListener(ChangeListener l) {
changeListeners.add(l);
} public void removeChangeListener(ChangeListener l) {
changeListeners.remove(l);
} // 选得鼠标选中的颜色
public Color getColorAt(int x, int y) {
// 如果不在显示颜色的图片中,则返回null
if (!colorsImageRect.contains(x, y)) { return null; } // 以图片的左上角为原点
x -= colorsImageRect.getX();
y -= colorsImageRect.getY(); if (y <= getHeightOfColorsRect(storedColors)) {
int i = y / colorRectHeight * columnSize + x / colorRectWidth;
return i >= storedColors.size() ? null : storedColors.get(i);
} else {
y -= getHeightOfColorsRect(storedColors) + margin;
int i = y / colorRectHeight * columnSize + x / colorRectWidth;
return i >= defaultColors.size() ? null : defaultColors.get(i);
}
} // 返回当前选中的颜色
public Color getColor() {
return color;
} // 设置当前颜色
public void setColor(Color color) {
this.color = (color == null) ? Color.WHITE : color;
setSliderValues(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
} public void setColor(int r, int g, int b) {
this.color = new Color(r, g, b, 255);
setSliderValues(r, g, b, 255);
} public void setColor(int r, int g, int b, int a) {
r = clamp(r);
g = clamp(g);
b = clamp(b);
a = clamp(a);
this.color = new Color(r, g, b, a);
setSliderValues(r, g, b, a);
} public void setR(int r) {
setColor(r, color.getGreen(), color.getBlue(), color.getAlpha());
} public void setG(int g) {
setColor(color.getRed(), g, color.getBlue(), color.getAlpha());
} public void setB(int b) {
setColor(color.getRed(), color.getGreen(), b, color.getAlpha());
} public void setA(int a) {
setColor(color.getRed(), color.getGreen(), color.getBlue(), a);
} public int clamp(int val) {
val = val < 0 ? 0 : val;
val = val > 255 ? 255 : val;
return val;
} // 设置slier的值
private void setSliderValues(int r, int g, int b, int a) {
redSlider.setValue(r);
greenSlider.setValue(g);
blueSlider.setValue(b);
alphaSlider.setValue(a); fireStateChanged();
} /**
* 把16进制模式的字符串转化成颜色.
*
* @param hex
* 表示颜色的16进制字符串,格式为#rgb, #rrggbb, #aarrggbb
* @return 返回字符串的颜色,如果字符串格式不对,返回null
*/
public static Color parseColorHex(String hex) {
// #rgb, #rrggbb, #aarrggbb
// 检查长度
if (hex == null || hex.length() != 4 && hex.length() != 7 && hex.length() != 9
&& hex.charAt(0) != '#') { return null; } // 检查字符是否有效
for (int i = 1; i < hex.length(); ++i) {
char aChar = hex.charAt(i);
if (!('0' <= aChar && aChar <= '9') && !('a' <= aChar && aChar <= 'f')
&& !('A' <= aChar && aChar <= 'F')) { return null; }
} if (hex.length() == 4) {
// #rgb
int r = Integer.valueOf(hex.charAt(1) + "" + hex.charAt(1), 16);
int g = Integer.valueOf(hex.charAt(2) + "" + hex.charAt(2), 16);
int b = Integer.valueOf(hex.charAt(3) + "" + hex.charAt(3), 16);
return new Color(r, g, b);
} else if (hex.length() == 7) {
// #rrggbb
int r = Integer.valueOf(hex.substring(1, 3), 16);
int g = Integer.valueOf(hex.substring(3, 5), 16);
int b = Integer.valueOf(hex.substring(5, 7), 16);
return new Color(r, g, b);
} else if (hex.length() == 9) {
// #aarrggbb
int a = Integer.valueOf(hex.substring(1, 3), 16);
int r = Integer.valueOf(hex.substring(3, 5), 16);
int g = Integer.valueOf(hex.substring(5, 7), 16);
int b = Integer.valueOf(hex.substring(7, 9), 16);
return new Color(r, g, b, a);
} return null;
} public static char[] hexDight = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
'C', 'D', 'E', 'F' }; /**
* 把颜色的表示转换为16进制表示#rrggbbaa
*
* @param color
* @return 返回颜色的16进制字符串
*/
public static String colorToHexString(Color color) {
if (color == null) { return "null"; }
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
int a = color.getAlpha(); StringBuilder sb = new StringBuilder("#");
sb.append(hexDight[a >> 4 & 0xF]);
sb.append(hexDight[a & 0xF]);
sb.append(hexDight[r >> 4 & 0xF]);
sb.append(hexDight[r & 0xF]);
sb.append(hexDight[g >> 4 & 0xF]);
sb.append(hexDight[g & 0xF]);
sb.append(hexDight[b >> 4 & 0xF]);
sb.append(hexDight[b & 0xF]); return sb.toString();
} private void prepareColors() {
// 从文件中读取颜色
try {
Scanner scanner = new Scanner(new File("resources/colors.txt"));
while (scanner.hasNextLine()) {
try {
Color c = parseColorHex(scanner.nextLine().trim());
if (c != null) {
storedColors.add(c);
}
} catch (Exception e) {
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} // 创建一些默认的颜色
final float delta = 0.2f;
for (float r = 0; r <= 1.0; r += delta) {
for (float g = 0; g <= 1.0; g += delta) {
for (float b = 0; b <= 1.0; b += delta) {
defaultColors.add(new Color(r, g, b));
}
}
}
} private int getHeightOfColorsRect(List<Color> li) {
int row = (int) Math.ceil(li.size() / (float) columnSize); return row * colorRectWidth;
} private void prepareColorsImage() {
margin = padding.top;
int w = columnSize * colorRectWidth;
int h = getHeightOfColorsRect(storedColors) + getHeightOfColorsRect(defaultColors) + margin;
int x = 0;
int y = 0; colorsImageRect.setRect(padding.top, padding.top, w, h);
colorsImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = colorsImage.createGraphics(); // 绘制用户存储的颜色
for (int i = 0; i < storedColors.size(); ++i) {
g2d.setPaint(storedColors.get(i));
g2d.fillRect(x, y, colorRectWidth, colorRectHeight); x += colorRectWidth; if ((i + 1) % columnSize == 0) {
x = 0;
y += colorRectHeight;
}
} x = 0;
y = getHeightOfColorsRect(storedColors) + margin; // 绘制默认的颜色
for (int i = 0; i < defaultColors.size(); ++i) {
g2d.setPaint(defaultColors.get(i));
g2d.fillRect(x, y, colorRectWidth, colorRectHeight); x += colorRectWidth; if ((i + 1) % columnSize == 0) {
x = 0;
y += colorRectHeight;
}
}
} private void prepareSize() {
width = padding.left + colorsImage.getWidth() + padding.right;
height = padding.top + colorsImage.getHeight() + padding.top + previewHeight + sliderHeight;
} private void preparePreview() {
int x = padding.left;
int y = height - sliderHeight - previewHeight;
int w = width - padding.left - padding.right;
previewRect.setRect(x, y, w, previewHeight);
} private void prepareSliders() {
setLayout(null);
int margin = 0; // slider之间的间隔,实际没必须
int h = sliderHeight;
int w = (width - padding.left - padding.right) / 4;
int x = padding.left;
int y = height - h + 2; redSlider.setBounds(x, y, w, h);
x += w + margin;
greenSlider.setBounds(x, y, w, h);
x += w + margin;
blueSlider.setBounds(x, y, w, h);
x += w + margin;
alphaSlider.setBounds(x, y, w, h); add(redSlider);
add(greenSlider);
add(blueSlider);
add(alphaSlider);
} @Override
public Dimension getMinimumSize() {
return new Dimension(width, height);
} @Override
public Dimension getMaximumSize() {
return new Dimension(width, height);
} @Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
} [html] view plain copy
package gradient; import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D; /**
* 绘制Photoshop中透明色的效果.
*
* @author Biao
*
*/
public class TransparentPainter {
public static void paint(Graphics2D g2d, Rectangle2D rect) {
g2d.setClip(rect);
int sx = (int) rect.getX();
int sy = (int) rect.getY();
int w = (int) rect.getWidth();
int h = (int) rect.getHeight(); Color color = Color.WHITE;
Color color1 = Color.WHITE;
Color color2 = Color.LIGHT_GRAY;
int delta = 10;
boolean odd = false;
for (int y = sy; y <= h + sy; y += delta) {
color = (odd) ? color1 : color2;
for (int x = sx; x <= w + sx; x += delta) {
g2d.setPaint(color);
g2d.fillRect(x, y, w, h); color = (color == color1) ? color2 : color1;
} odd = !odd;
}
g2d.setClip(null);
}
} [html] view plain copy
package gradient;
import java.awt.geom.Point2D; public class GeometryUtil {
// 两点之间的距离
public static double distanceOfPoints(Point2D p1, Point2D p2) {
double disX = p2.getX() - p1.getX();
double disY = p2.getY() - p1.getY();
double dis = Math.sqrt(disX * disX + disY * disY); return dis;
} // 两点的中点
public static Point2D middlePoint(Point2D p1, Point2D p2) {
double x = (p1.getX() + p2.getX()) / 2;
double y = (p1.getY() + p2.getY()) / 2; return new Point2D.Double(x, y);
} // 在两点所在直线上,以从startPoint到endPoint为方向,离startPoint的距离disToStartPoint的点
public static Point2D extentPoint(Point2D startPoint, Point2D endPoint, double disToStartPoint) {
double disX = endPoint.getX() - startPoint.getX();
double disY = endPoint.getY() - startPoint.getY();
double dis = Math.sqrt(disX * disX + disY * disY);
double sin = (endPoint.getY() - startPoint.getY()) / dis;
double cos = (endPoint.getX() - startPoint.getX()) / dis;
double deltaX = disToStartPoint * cos;
double deltaY = disToStartPoint * sin; return new Point2D.Double(startPoint.getX() + deltaX, startPoint.getY() + deltaY);
}
}
  1. package gradient;
  2. import java.awt.Color;
  3. import java.awt.Dimension;
  4. import java.awt.Graphics;
  5. import java.awt.Graphics2D;
  6. import java.awt.Insets;
  7. import java.awt.LinearGradientPaint;
  8. import java.awt.MultipleGradientPaint;
  9. import java.awt.Paint;
  10. import java.awt.RadialGradientPaint;
  11. import java.awt.RenderingHints;
  12. import java.awt.event.KeyAdapter;
  13. import java.awt.event.KeyEvent;
  14. import java.awt.event.MouseAdapter;
  15. import java.awt.event.MouseEvent;
  16. import java.awt.event.MouseMotionAdapter;
  17. import java.awt.geom.Ellipse2D;
  18. import java.awt.geom.GeneralPath;
  19. import java.awt.geom.Point2D;
  20. import java.awt.geom.Rectangle2D;
  21. import java.util.ArrayList;
  22. import java.util.LinkedList;
  23. import java.util.List;
  24. import javax.swing.JFrame;
  25. import javax.swing.JPanel;
  26. import javax.swing.event.ChangeEvent;
  27. import javax.swing.event.ChangeListener;
  28. /*
  29. 使用方法:
  30. 渐变窗体:
  31. a. 左键双击顶点的linear gradient 渐变区,改变渐变超出范围的重复绘制模式.
  32. b. 左键双击fractions小按钮区,创建添加一个新的fraction按钮.
  33. c. 左键双击fractions小按钮,弹出窗口选择窗口选择颜色.
  34. d. 右键双击fractions小按钮,删除此fraction按钮.
  35. e. 按住fractions小按钮可以拖动它,修改fractions的位置.
  36. f. 左键双击辐射渐变区,改变辐射渐变的焦点(focus)到点击位置.
  37. g. 在辐射渐变区按住左键拖动,改变辐射渐变的焦点.
  38. h. 按下f,显示辐射渐变的圆周,为了方便看到更清楚的数据,默认这圆周是隐藏的.
  39. i. 按下c,恢复辐射渐变的焦点到辐射渐变的圆心,焦点默认是与圆心重合.
  40. 颜色选择窗体:
  41. a. 单击某一个颜色,则选中此颜色,并在底部的预览区显示出来.但颜色选择窗口不消失.
  42. b. 双击某一个颜色,则选中此颜色,返回给调用者,颜色选择窗口消失.
  43. c. 按下回车键,返回选中的颜色,颜色选择窗口消失.
  44. d. 按下ESC键,返回传给颜色选择窗体的默认色,颜色选择窗口消失.
  45. e. 下部的JSlider依次调节被选中颜色的red, green, blue, alpha,拖动并实时的在预览区显示出调整后颜色.
  46. 第三方程序集成使用方法: 在第三方程序中创建一个GradientGenerator对象,并添加到组件的某一部分,
  47. 并给此gradientGenerator添加上change listener:
  48. gradientGenerator.addChangeListener(new ChangedListener() {
  49. public void stateChanged(ChangeEvent e) {
  50. float[] fractions = gradientGenerator.getFractons();
  51. Color[] colors = gradientGenerator.getColors();
  52. Point2D focus = gradientGenerator.calculateFocus(center, radius);
  53. repaint(); // 使用这里得到的fractions, colors, focus等去绘制第三方程序中的渐变图形
  54. });
  55. 这样,当gradient generator中的数据发生变化时,第三方程序里也会即时的反映出来.
  56. 1. 提示,现在Swing支持合建不规则窗体。
  57. 2. 此程序中,除了JSlider,其他的部分都是使用Java2D手动计算绘制出来的。
  58. 基于上面两点,可以自己创建一个统一的JSlider风格,
  59. 然后就可以把整个程序的外观风格做得在所有平台下都是一个样。
  60. */
  61. /**
  62. * *^o^*,本程序一惯还是一惯的作风,LGPL协议,什么版权的废话就不整了,希望修改得效果好的朋友给大家分享一下心得,在此权当扔出块板砖,
  63. * 希望能砸出块暖玉来,嗷呜嗷呜嗷呜.
  64. */
  65. @SuppressWarnings("serial")
  66. public class GradientGenerator extends JPanel {
  67. private int width = 400; // 整个Panel的宽度
  68. private int height = 400; // 整个Panel的高度
  69. private Insets padding = new Insets(10, 10, 10, 10); // 边距
  70. private int thumbRectHeight = 20; // Fraction按钮区的高度
  71. private int linearRectHeight = 40; // 线性渐变区域的高度
  72. private int radialRectHeight = 310; // 辐射渐变区域的高度
  73. private Ellipse2D radialCircle = new Ellipse2D.Float(); // 辐射渐变的圆周
  74. private Point2D focusPoint = new Point2D.Float(); // 辐射渐变的焦点
  75. private Point2D pressedPoint = new Point2D.Float(); // 鼠标按下时的点
  76. private Rectangle2D linearRect = new Rectangle2D.Float(); // 线性渐变区域
  77. private Rectangle2D thumbsRect = new Rectangle2D.Float(); // Fractions按钮区域
  78. private Rectangle2D radialRect = new Rectangle2D.Float(); // 辐射渐变区域
  79. private Thumb selectedThumb = null; // 被选中的Fraction按钮
  80. private List<Thumb> thumbs = new ArrayList<Thumb>(); // Fractions按钮
  81. private boolean showCircle = false; // 显示辐射渐变的圆周
  82. private List<ChangeListener> changeListeners = new LinkedList<ChangeListener>();
  83. private MultipleGradientPaint.CycleMethod cycleMethod = MultipleGradientPaint.CycleMethod.REFLECT;
  84. /**
  85. * 返回渐变的fractions数组
  86. *
  87. * @return
  88. */
  89. public float[] getGradientFractions() {
  90. float[] fractions = new float[thumbs.size()];
  91. int i = 0;
  92. for (Thumb t : thumbs) {
  93. fractions[i] = (float) ((t.getX() - padding.left) / linearRect.getWidth());
  94. ++i;
  95. }
  96. return fractions;
  97. }
  98. /**
  99. * 返回渐变的colors数组
  100. *
  101. * @return
  102. */
  103. public Color[] getGradientColors() {
  104. Color[] colors = new Color[thumbs.size()];
  105. int i = 0;
  106. for (Thumb t : thumbs) {
  107. colors[i] = t.getColor();
  108. ++i;
  109. }
  110. return colors;
  111. }
  112. /**
  113. * 利用指定圆的圆心和半径和当前的辐射渐变数据,计算相对于指定圆的焦点
  114. *
  115. * @param center
  116. *        圆心
  117. * @param radius
  118. *        半径
  119. * @return 返回相对于指定圆的焦点
  120. */
  121. public Point2D calculateFocus(Point2D center, double radius) {
  122. Point2D curCenter = new Point2D.Double(radialCircle.getCenterX(), radialCircle.getCenterY());
  123. double curRadius = radialCircle.getWidth() / 2;
  124. double curFocusLen = GeometryUtil.distanceOfPoints(curCenter, focusPoint);
  125. double newFocusLen = radius * curFocusLen / curRadius;
  126. Point2D newFocusPoint = GeometryUtil.extentPoint(curCenter, focusPoint, newFocusLen);
  127. // 先移回原点,再移动到center的位置
  128. newFocusPoint.setLocation(center.getX() - curCenter.getX(),
  129. center.getY() - curCenter.getY());
  130. return newFocusPoint;
  131. }
  132. public GradientGenerator() {
  133. setFocusable(true); // 为了能接收键盘按键事件
  134. afterResized();
  135. resetThumbs(new float[] { 0.0f, 0.5f, 1.0f }, new Color[] { Color.BLACK, Color.BLUE,
  136. new Color(255, 255, 255, 220) });
  137. handleEvents();
  138. setBackground(Color.DARK_GRAY);
  139. }
  140. // 事件处理
  141. private void handleEvents() {
  142. this.addMouseListener(new MouseAdapter() {
  143. @Override
  144. public void mousePressed(MouseEvent e) {
  145. int x = e.getX();
  146. int y = e.getY();
  147. pressedPoint.setLocation(x, y);
  148. // 得到被选中的Thumb
  149. for (Thumb t : thumbs) {
  150. if (t.contains(x, y)) {
  151. t.setSelected(true);
  152. selectedThumb = t;
  153. break;
  154. }
  155. }
  156. repaint();
  157. }
  158. @Override
  159. public void mouseReleased(MouseEvent e) {
  160. for (Thumb t : thumbs) {
  161. t.setSelected(false);
  162. selectedThumb = null;
  163. }
  164. repaint();
  165. }
  166. @Override
  167. public void mouseClicked(MouseEvent e) {
  168. int x = e.getX();
  169. int y = e.getY();
  170. // 左键双击
  171. if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
  172. // 如果在thumbs里面,则弹出颜色选择器
  173. for (Thumb t : thumbs) {
  174. if (t.contains(x, y)) {
  175. changeThumbColor(t);
  176. repaint();
  177. return;
  178. }
  179. }
  180. // 如果不在thumbs里,而在thumbs的区域里,则增加一个thumb
  181. if (thumbsRect.contains(x, y)) {
  182. insertThumbAt(x);
  183. repaint();
  184. return;
  185. }
  186. // 修改focus的位置
  187. if (radialRect.contains(x, y)) {
  188. changeFocusPoint(new Point2D.Float(x, y));
  189. repaint();
  190. return;
  191. }
  192. // 在Linear rect里面,修改cycle method
  193. if (linearRect.contains(x, y)) {
  194. changeCycleMethod();
  195. repaint();
  196. return;
  197. }
  198. } else if (e.getButton() == MouseEvent.BUTTON3 && e.getClickCount() == 2) {
  199. // 右键双击
  200. removeThumbAt(x, y);
  201. return;
  202. }
  203. }
  204. });
  205. this.addMouseMotionListener(new MouseMotionAdapter() {
  206. @Override
  207. public void mouseDragged(MouseEvent e) {
  208. // 拖动滑块
  209. if (selectedThumb != null) {
  210. int deltaX = e.getX() - (int) (selectedThumb.getX());
  211. int x = selectedThumb.getX() + deltaX;
  212. // 不能超过边界
  213. int maxRight = (int) (padding.left + linearRect.getWidth());
  214. if (x < padding.left || x > maxRight) { return; }
  215. int index = thumbs.indexOf(selectedThumb);
  216. int prevX = Integer.MIN_VALUE;
  217. int nextX = Integer.MAX_VALUE;
  218. // 只能在前一个和后一个之间移动
  219. if (index - 1 >= 0) {
  220. prevX = (int) (thumbs.get(index - 1).getX());
  221. }
  222. if (index + 1 < thumbs.size()) {
  223. nextX = (int) (thumbs.get(index + 1).getX());
  224. }
  225. if (x > prevX && x < nextX) {
  226. selectedThumb.setX(x);
  227. repaint();
  228. }
  229. return;
  230. } else if (radialRect.contains(e.getX(), e.getY())) {
  231. int deltaX = (int) (e.getX() - pressedPoint.getX());
  232. int deltaY = (int) (e.getY() - pressedPoint.getY());
  233. focusPoint.setLocation(focusPoint.getX() + deltaX, focusPoint.getY() + deltaY);
  234. pressedPoint.setLocation(e.getX(), e.getY());
  235. repaint();
  236. }
  237. }
  238. });
  239. this.addKeyListener(new KeyAdapter() {
  240. @Override
  241. public void keyReleased(KeyEvent e) {
  242. switch (e.getKeyCode()) {
  243. case KeyEvent.VK_F:
  244. showCircle = !showCircle;
  245. break;
  246. case KeyEvent.VK_C:
  247. changeFocusPoint(radialCircle.getCenterX(), radialCircle.getCenterY());
  248. break;
  249. }
  250. repaint();
  251. }
  252. });
  253. }
  254. // 执行监听器的事件
  255. public void fireChangeEvent() {
  256. for (ChangeListener l : changeListeners) {
  257. l.stateChanged(new ChangeEvent(this));
  258. }
  259. }
  260. // 改变超出渐变区的颜色渐变方式
  261. public void changeCycleMethod() {
  262. changeCycleMethod(cycleMethod);
  263. }
  264. public void changeCycleMethod(MultipleGradientPaint.CycleMethod cycleMethod) {
  265. switch (cycleMethod) {
  266. case NO_CYCLE:
  267. this.cycleMethod = MultipleGradientPaint.CycleMethod.REFLECT;
  268. break;
  269. case REFLECT:
  270. this.cycleMethod = MultipleGradientPaint.CycleMethod.REPEAT;
  271. break;
  272. case REPEAT:
  273. this.cycleMethod = MultipleGradientPaint.CycleMethod.NO_CYCLE;
  274. break;
  275. }
  276. }
  277. @Override
  278. protected void paintComponent(Graphics g) {
  279. super.paintComponent(g);
  280. Graphics2D g2d = (Graphics2D) g;
  281. g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  282. drawLinearRect(g2d);
  283. drawThumbsRect(g2d);
  284. drawRadialRect(g2d);
  285. }
  286. // 绘制fraction按钮所在区域
  287. private void drawThumbsRect(Graphics2D g2d) {
  288. g2d.setColor(new Color(255, 255, 255, 40));
  289. g2d.fill(thumbsRect);
  290. // 绘制fraction按钮
  291. for (Thumb t : thumbs) {
  292. t.paint(g2d);
  293. }
  294. }
  295. private void drawLinearRect(Graphics2D g2d) {
  296. // 绘制线性渐变区域
  297. float sx = (float) linearRect.getX();
  298. float sy = (float) linearRect.getY();
  299. float ex = (int) (sx + linearRect.getWidth());
  300. float ey = sy;
  301. float[] fractions = getGradientFractions();
  302. Color[] colors = getGradientColors();
  303. Paint p = new LinearGradientPaint(sx, sy, ex, ey, fractions, colors, cycleMethod);
  304. TransparentPainter.paint(g2d, linearRect);
  305. g2d.setPaint(p);
  306. g2d.fill(linearRect);
  307. }
  308. // 绘制辐射渐变区
  309. private void drawRadialRect(Graphics2D g2d) {
  310. float cx = (float) radialCircle.getCenterX();
  311. float cy = (float) radialCircle.getCenterY();
  312. float fx = (float) focusPoint.getX();
  313. float fy = (float) focusPoint.getY();
  314. float radius = (float) radialCircle.getWidth() / 2;
  315. float[] fractions = getGradientFractions();
  316. Color[] colors = getGradientColors();
  317. TransparentPainter.paint(g2d, radialRect);
  318. Paint p = new RadialGradientPaint(cx, cy, radius, fx, fy, fractions, colors, cycleMethod);
  319. g2d.setPaint(p);
  320. g2d.fill(radialRect);
  321. if (showCircle) {
  322. // 绘制辐射渐变的圆
  323. g2d.setPaint(Color.BLACK);
  324. g2d.draw(radialCircle);
  325. }
  326. }
  327. // 最少需要两个渐变值,所以开始就创建两个fraction
  328. public void resetThumbs(float[] fractions, Color[] colors) {
  329. if (fractions == null || colors == null) { throw new NullPointerException(); }
  330. if (fractions.length != colors.length) { throw new IllegalArgumentException(
  331. "Fractions 和 Colors 参数个数不等"); }
  332. int x = (int) thumbsRect.getX();
  333. int w = (int) thumbsRect.getWidth();
  334. for (int i = 0; i < fractions.length; ++i) {
  335. insertThumbAt(x + (int) (w * fractions[i]), colors[i]);
  336. }
  337. }
  338. // 在指定的水平位置插入Fraction按钮
  339. private void insertThumbAt(int x) {
  340. insertThumbAt(x, Color.BLUE);
  341. }
  342. private void insertThumbAt(int x, Color color) {
  343. int index = 0;
  344. for (Thumb t : thumbs) {
  345. if (x > t.getX()) {
  346. index++;
  347. }
  348. }
  349. int y = (int) (padding.top + linearRect.getHeight());
  350. thumbs.add(index, new Thumb(x, y, color));
  351. fireChangeEvent();
  352. }
  353. public void removeThumbAt(int x, int y) {
  354. for (Thumb t : thumbs) {
  355. if (t.contains(x, y)) {
  356. if (thumbs.size() > 2) {
  357. thumbs.remove(t);
  358. fireChangeEvent();
  359. break;
  360. }
  361. }
  362. }
  363. }
  364. private void changeThumbColor(Thumb thumb) {
  365. // 弹出颜色选择器
  366. Color newColor = ColorChooser.chooseColor(this, thumb.getColor());
  367. if (newColor != null) {
  368. thumb.setColor(newColor);
  369. fireChangeEvent();
  370. }
  371. }
  372. // 改变焦点的位置
  373. public void changeFocusPoint(double x, double y) {
  374. focusPoint.setLocation(x, y);
  375. fireChangeEvent();
  376. }
  377. private void changeFocusPoint(Point2D focusPoint) {
  378. changeFocusPoint(focusPoint.getX(), focusPoint.getY());
  379. }
  380. // 当panel的大小改变时,再次调用此函数更新显示区域
  381. private void afterResized() {
  382. // ////////////////////////////////////////
  383. // padding-top
  384. // linear gradient area
  385. // thumbs area
  386. // padding = padding top
  387. // radial gradient area
  388. // padding-bottom
  389. // ///////////////////////////////////////
  390. // 线性渐变显示区域
  391. int x = padding.left;
  392. int y = padding.top;
  393. int w = width - padding.left - padding.right;
  394. int h = linearRectHeight;
  395. linearRect.setRect(x, y, w, h);
  396. // Fraction按钮所在区域
  397. y += linearRectHeight;
  398. h = thumbRectHeight;
  399. thumbsRect.setRect(x, y, w, h);
  400. // 辐射渐变显示区域
  401. y = padding.top + linearRectHeight + thumbRectHeight + padding.top;
  402. h = radialRectHeight;
  403. h = Math.min(w, h);
  404. x = (width - w) / 2;
  405. radialRect.setRect(x, y, w, h);
  406. // 中心点和焦点
  407. int cx = x + w / 2;
  408. int cy = y + h / 2;
  409. int radius = 100;
  410. focusPoint.setLocation(cx, cy);
  411. radialCircle.setFrame(cx - radius, cy - radius, radius + radius, radius + radius);
  412. repaint();
  413. }
  414. @Override
  415. public Dimension getMinimumSize() {
  416. return new Dimension(width, height);
  417. }
  418. @Override
  419. public Dimension getMaximumSize() {
  420. return new Dimension(width, height);
  421. }
  422. @Override
  423. public Dimension getPreferredSize() {
  424. return new Dimension(width, height);
  425. }
  426. private static void createGuiAndShow() {
  427. JFrame frame = new JFrame("Gradient Generator");
  428. JPanel panel = new JPanel();
  429. panel.add(new GradientGenerator());
  430. frame.setContentPane(new GradientGenerator());
  431. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  432. frame.pack(); // 使用此函数后always on top就不起作用了
  433. frame.setResizable(false);
  434. frame.setLocationRelativeTo(null);
  435. frame.setAlwaysOnTop(true);
  436. frame.setVisible(true);
  437. }
  438. public static void main(String[] args) {
  439. createGuiAndShow();
  440. }
  441. }
  442. class Thumb {
  443. private int x;
  444. private int y;
  445. private int width = 16;
  446. private int height = 20;
  447. private Color color;
  448. private boolean selected;
  449. private GeneralPath outerPath;
  450. private GeneralPath innerPath;
  451. public Thumb(int x, int y, Color color) {
  452. setXY(x, y);
  453. this.color = color;
  454. }
  455. public int getX() {
  456. return x;
  457. }
  458. public void setX(int x) {
  459. setXY(x, y);
  460. }
  461. public int getY() {
  462. return y;
  463. }
  464. public void setY(int y) {
  465. setXY(x, y);
  466. }
  467. public int getWidth() {
  468. return width;
  469. }
  470. public void setWidth(int width) {
  471. setWidthHeight(width, height);
  472. }
  473. public int getHeight() {
  474. return height;
  475. }
  476. public void setHeight(int height) {
  477. setWidthHeight(width, height);
  478. }
  479. public Color getColor() {
  480. return color;
  481. }
  482. public void setColor(Color color) {
  483. this.color = color;
  484. }
  485. public boolean isSelected() {
  486. return selected;
  487. }
  488. public void setSelected(boolean selected) {
  489. this.selected = selected;
  490. }
  491. public boolean contains(int x, int y) {
  492. return outerPath.contains(x, y);
  493. }
  494. public void setXY(int x, int y) {
  495. this.x = x;
  496. this.y = y;
  497. createPaths();
  498. }
  499. public void setWidthHeight(int width, int height) {
  500. this.width = width;
  501. this.height = height;
  502. createPaths();
  503. }
  504. private float[] fractions = new float[] { 0.0f, 0.5f, 1.0f };
  505. private Color[] colors = new Color[] { Color.ORANGE, Color.BLACK, Color.ORANGE.brighter() };
  506. public void paint(Graphics2D g2d) {
  507. // 绘制大三角形按钮
  508. // Paint p = new GradientPaint(x, y, selected ? color.darker() : color,
  509. // x, y + height, Color.ORANGE);
  510. Paint p = new LinearGradientPaint(x - width, y, x + width / 4, y, fractions, colors);
  511. g2d.setPaint(p);
  512. g2d.fill(outerPath);
  513. // 绘制小三角形按钮
  514. g2d.setColor(color);
  515. g2d.fill(innerPath);
  516. }
  517. // 创建按钮的形状
  518. private void createPaths() {
  519. outerPath = new GeneralPath();
  520. outerPath.moveTo(x, y);
  521. outerPath.lineTo(x + width / 2, y + height);
  522. outerPath.lineTo(x - width / 2, y + height);
  523. outerPath.closePath();
  524. innerPath = new GeneralPath();
  525. innerPath.moveTo(x, y + height / 2);
  526. innerPath.lineTo(x + width / 4, y + height);
  527. innerPath.lineTo(x - width / 4, y + height);
  528. innerPath.closePath();
  529. }
  530. }
[html] view plain copy
 
  1. package gradient;
  2. import java.awt.AWTEvent;
  3. import java.awt.BorderLayout;
  4. import java.awt.Color;
  5. import java.awt.Component;
  6. import java.awt.Dimension;
  7. import java.awt.Graphics;
  8. import java.awt.Graphics2D;
  9. import java.awt.Insets;
  10. import java.awt.RenderingHints;
  11. import java.awt.Toolkit;
  12. import java.awt.event.AWTEventListener;
  13. import java.awt.event.KeyEvent;
  14. import java.awt.event.MouseAdapter;
  15. import java.awt.event.MouseEvent;
  16. import java.awt.event.WindowAdapter;
  17. import java.awt.event.WindowEvent;
  18. import java.awt.geom.Rectangle2D;
  19. import java.awt.image.BufferedImage;
  20. import java.io.File;
  21. import java.io.FileNotFoundException;
  22. import java.util.ArrayList;
  23. import java.util.List;
  24. import java.util.Scanner;
  25. import javax.swing.JComponent;
  26. import javax.swing.JDialog;
  27. import javax.swing.JPanel;
  28. import javax.swing.JSlider;
  29. import javax.swing.event.ChangeEvent;
  30. import javax.swing.event.ChangeListener;
  31. /**
  32. * 创建一个模态的颜色选择对话框,可以加载用户预先定义存储好的颜色.
  33. *
  34. * @author Biao
  35. *
  36. */
  37. @SuppressWarnings("serial")
  38. public class ColorChooser extends JDialog {
  39. private static ColorChooser instance = new ColorChooser();
  40. private ColorPanel colorPanel = new ColorPanel();
  41. private Color color;
  42. public static Color chooseColor(JComponent ower, Color defaultColor) {
  43. instance.color = defaultColor;
  44. instance.colorPanel.startSelect(defaultColor);
  45. instance.pack();
  46. instance.setLocationRelativeTo(ower);
  47. instance.setVisible(true);
  48. return instance.color;
  49. }
  50. private ColorChooser() {
  51. setTitle("Choose a color");
  52. setModal(true);
  53. setResizable(false);
  54. setBackground(Color.DARK_GRAY);
  55. getContentPane().add(colorPanel, BorderLayout.CENTER);
  56. this.addWindowListener(new WindowAdapter() {
  57. @Override
  58. public void windowClosing(WindowEvent e) {
  59. gotoHell(color);
  60. }
  61. });
  62. colorPanel.addChangeListener(new ChangeListener() {
  63. @Override
  64. public void stateChanged(ChangeEvent e) {
  65. Color c = colorPanel.getColor();
  66. if (colorPanel.isDoubleClickSelection()) {
  67. gotoHell(c);
  68. }
  69. int r = c.getRed();
  70. int g = c.getGreen();
  71. int b = c.getBlue();
  72. int a = c.getAlpha();
  73. String hex = ColorPanel.colorToHexString(new Color(r, g, b, a));
  74. String title = String.format("RGBA(%d,%d,%d,%d) Hex(%s)", r, g, b, a, hex);
  75. setTitle(title);
  76. }
  77. });
  78. // 处理JDialog所有子组件的按键事件
  79. // 按下回车使用选择的颜色,按下Esc返回默认传进来的颜色
  80. Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
  81. @Override
  82. public void eventDispatched(AWTEvent event) {
  83. KeyEvent ke = (KeyEvent) event;
  84. if (ke.getID() == KeyEvent.KEY_PRESSED) {
  85. if (event.getSource() instanceof Component) {
  86. Component com = (Component) event.getSource();
  87. if (ke.getKeyCode() == KeyEvent.VK_ESCAPE && hasChild(com)) {
  88. gotoHell(color); // 取消时返回默认的颜色
  89. } else if (ke.getKeyCode() == KeyEvent.VK_ENTER && hasChild(com)) {
  90. gotoHell(colorPanel.getColor());
  91. }
  92. }
  93. }
  94. }
  95. }, AWTEvent.KEY_EVENT_MASK);
  96. }
  97. // 是否包含了组件
  98. public boolean hasChild(Component c) {
  99. for (Component parent = c; parent != null; parent = parent.getParent()) {
  100. if (parent == this) { return true; }
  101. }
  102. return false;
  103. }
  104. // 隐藏颜色选择对话框
  105. public void gotoHell(Color c) {
  106. color = (c == null) ? color : c;
  107. setVisible(false);
  108. }
  109. }
  110. @SuppressWarnings("serial")
  111. class ColorPanel extends JPanel {
  112. final static private int columnSize = 21; // 每行最多显示21个颜色
  113. final static private int sliderHeight = 20; // Slider的高度
  114. final static private int previewHeight = 20; // 预览区的高度
  115. final static private int colorRectWidth = 20; // 颜色小方块的宽度
  116. final static private int colorRectHeight = 20;// 颜色小方块的高度
  117. private int width = 520; // Color panel的尺寸
  118. private int height = 340;
  119. private Insets padding = new Insets(10, 10, 0, 10); // 边距
  120. private int margin = padding.top;
  121. private Color color = Color.WHITE;
  122. private List<Color> storedColors = new ArrayList<Color>(); // 用户存储的颜色
  123. private List<Color> defaultColors = new ArrayList<Color>(); // 使用算法生成的默认颜色
  124. private Rectangle2D previewRect = new Rectangle2D.Float(); // 预览区域
  125. private Rectangle2D colorsImageRect = new Rectangle2D.Double(); // 显示颜色的区域
  126. private BufferedImage colorsImage; // 需要使用颜色信息来创建确定大小
  127. // 调节rgba的slider
  128. private JSlider redSlider = new JSlider(0, 255, 255);
  129. private JSlider greenSlider = new JSlider(0, 255, 255);
  130. private JSlider blueSlider = new JSlider(0, 255, 255);
  131. private JSlider alphaSlider = new JSlider(0, 255, 255);
  132. // 双击时如果选中颜色,则选择完成
  133. private boolean doubleClickSelection = false;
  134. private List<ChangeListener> changeListeners = new ArrayList<ChangeListener>();
  135. public ColorPanel() {
  136. // 创建颜色和显示颜色的小方块缓冲图像
  137. prepareColors();
  138. prepareColorsImage();
  139. // 窗口的大小需要用color buffer image的大小来确定,所以必须在这里调用
  140. prepareSize();
  141. preparePreview();
  142. prepareSliders();
  143. this.addMouseListener(new MouseAdapter() {
  144. @Override
  145. public void mouseClicked(MouseEvent e) {
  146. int x = e.getX();
  147. int y = e.getY();
  148. Color c = getColorAt(x, y);
  149. if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1) {
  150. // 单击时设置选中的颜色
  151. if (c != null) {
  152. setColor(c);
  153. fireStateChanged();
  154. }
  155. } else if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
  156. // 双击时返回选中的颜色,隐藏颜色选取窗口
  157. if (c != null || previewRect.contains(x, y)) {
  158. setDoubleClickSelection(true);
  159. fireStateChanged();
  160. }
  161. }
  162. }
  163. });
  164. redSlider.addChangeListener(new ChangeListener() {
  165. @Override
  166. public void stateChanged(ChangeEvent e) {
  167. setR(redSlider.getValue());
  168. fireStateChanged();
  169. }
  170. });
  171. greenSlider.addChangeListener(new ChangeListener() {
  172. @Override
  173. public void stateChanged(ChangeEvent e) {
  174. setG(greenSlider.getValue());
  175. fireStateChanged();
  176. }
  177. });
  178. blueSlider.addChangeListener(new ChangeListener() {
  179. @Override
  180. public void stateChanged(ChangeEvent e) {
  181. setB(blueSlider.getValue());
  182. fireStateChanged();
  183. }
  184. });
  185. alphaSlider.addChangeListener(new ChangeListener() {
  186. @Override
  187. public void stateChanged(ChangeEvent e) {
  188. setA(alphaSlider.getValue());
  189. fireStateChanged();
  190. }
  191. });
  192. }
  193. @Override
  194. protected void paintComponent(Graphics g) {
  195. super.paintComponent(g);
  196. setBackground(Color.DARK_GRAY);
  197. Graphics2D g2d = (Graphics2D) g;
  198. g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  199. // 绘制颜色方块的缓冲图片
  200. int x = (int) colorsImageRect.getX();
  201. int y = (int) colorsImageRect.getY();
  202. int w = (int) colorsImageRect.getWidth();
  203. int h = (int) colorsImageRect.getHeight();
  204. g2d.drawImage(colorsImage, x, y, w, h, null);
  205. // 绘制颜色预览
  206. TransparentPainter.paint(g2d, previewRect);
  207. g2d.setPaint(color);
  208. g2d.fill(previewRect);
  209. }
  210. public void startSelect(Color color) {
  211. setColor(color);
  212. setDoubleClickSelection(false);
  213. }
  214. public boolean isDoubleClickSelection() {
  215. return doubleClickSelection;
  216. }
  217. protected void setDoubleClickSelection(boolean doubleClickSelection) {
  218. this.doubleClickSelection = doubleClickSelection;
  219. }
  220. // 当属性改变事件发生时,调用监听器并且重绘
  221. public void fireStateChanged() {
  222. for (ChangeListener l : changeListeners) {
  223. l.stateChanged(new ChangeEvent(this));
  224. }
  225. repaint();
  226. }
  227. public void addChangeListener(ChangeListener l) {
  228. changeListeners.add(l);
  229. }
  230. public void removeChangeListener(ChangeListener l) {
  231. changeListeners.remove(l);
  232. }
  233. // 选得鼠标选中的颜色
  234. public Color getColorAt(int x, int y) {
  235. // 如果不在显示颜色的图片中,则返回null
  236. if (!colorsImageRect.contains(x, y)) { return null; }
  237. // 以图片的左上角为原点
  238. x -= colorsImageRect.getX();
  239. y -= colorsImageRect.getY();
  240. if (y <= getHeightOfColorsRect(storedColors)) {
  241. int i = y / colorRectHeight * columnSize + x / colorRectWidth;
  242. return i >= storedColors.size() ? null : storedColors.get(i);
  243. } else {
  244. y -= getHeightOfColorsRect(storedColors) + margin;
  245. int i = y / colorRectHeight * columnSize + x / colorRectWidth;
  246. return i >= defaultColors.size() ? null : defaultColors.get(i);
  247. }
  248. }
  249. // 返回当前选中的颜色
  250. public Color getColor() {
  251. return color;
  252. }
  253. // 设置当前颜色
  254. public void setColor(Color color) {
  255. this.color = (color == null) ? Color.WHITE : color;
  256. setSliderValues(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
  257. }
  258. public void setColor(int r, int g, int b) {
  259. this.color = new Color(r, g, b, 255);
  260. setSliderValues(r, g, b, 255);
  261. }
  262. public void setColor(int r, int g, int b, int a) {
  263. r = clamp(r);
  264. g = clamp(g);
  265. b = clamp(b);
  266. a = clamp(a);
  267. this.color = new Color(r, g, b, a);
  268. setSliderValues(r, g, b, a);
  269. }
  270. public void setR(int r) {
  271. setColor(r, color.getGreen(), color.getBlue(), color.getAlpha());
  272. }
  273. public void setG(int g) {
  274. setColor(color.getRed(), g, color.getBlue(), color.getAlpha());
  275. }
  276. public void setB(int b) {
  277. setColor(color.getRed(), color.getGreen(), b, color.getAlpha());
  278. }
  279. public void setA(int a) {
  280. setColor(color.getRed(), color.getGreen(), color.getBlue(), a);
  281. }
  282. public int clamp(int val) {
  283. val = val < 0 ? 0 : val;
  284. val = val > 255 ? 255 : val;
  285. return val;
  286. }
  287. // 设置slier的值
  288. private void setSliderValues(int r, int g, int b, int a) {
  289. redSlider.setValue(r);
  290. greenSlider.setValue(g);
  291. blueSlider.setValue(b);
  292. alphaSlider.setValue(a);
  293. fireStateChanged();
  294. }
  295. /**
  296. * 把16进制模式的字符串转化成颜色.
  297. *
  298. * @param hex
  299. *        表示颜色的16进制字符串,格式为#rgb, #rrggbb, #aarrggbb
  300. * @return 返回字符串的颜色,如果字符串格式不对,返回null
  301. */
  302. public static Color parseColorHex(String hex) {
  303. // #rgb, #rrggbb, #aarrggbb
  304. // 检查长度
  305. if (hex == null || hex.length() != 4 && hex.length() != 7 && hex.length() != 9
  306. && hex.charAt(0) != '#') { return null; }
  307. // 检查字符是否有效
  308. for (int i = 1; i < hex.length(); ++i) {
  309. char aChar = hex.charAt(i);
  310. if (!('0' <= aChar && aChar <= '9') && !('a' <= aChar && aChar <= 'f')
  311. && !('A' <= aChar && aChar <= 'F')) { return null; }
  312. }
  313. if (hex.length() == 4) {
  314. // #rgb
  315. int r = Integer.valueOf(hex.charAt(1) + "" + hex.charAt(1), 16);
  316. int g = Integer.valueOf(hex.charAt(2) + "" + hex.charAt(2), 16);
  317. int b = Integer.valueOf(hex.charAt(3) + "" + hex.charAt(3), 16);
  318. return new Color(r, g, b);
  319. } else if (hex.length() == 7) {
  320. // #rrggbb
  321. int r = Integer.valueOf(hex.substring(1, 3), 16);
  322. int g = Integer.valueOf(hex.substring(3, 5), 16);
  323. int b = Integer.valueOf(hex.substring(5, 7), 16);
  324. return new Color(r, g, b);
  325. } else if (hex.length() == 9) {
  326. // #aarrggbb
  327. int a = Integer.valueOf(hex.substring(1, 3), 16);
  328. int r = Integer.valueOf(hex.substring(3, 5), 16);
  329. int g = Integer.valueOf(hex.substring(5, 7), 16);
  330. int b = Integer.valueOf(hex.substring(7, 9), 16);
  331. return new Color(r, g, b, a);
  332. }
  333. return null;
  334. }
  335. public static char[] hexDight = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
  336. 'C', 'D', 'E', 'F' };
  337. /**
  338. * 把颜色的表示转换为16进制表示#rrggbbaa
  339. *
  340. * @param color
  341. * @return 返回颜色的16进制字符串
  342. */
  343. public static String colorToHexString(Color color) {
  344. if (color == null) { return "null"; }
  345. int r = color.getRed();
  346. int g = color.getGreen();
  347. int b = color.getBlue();
  348. int a = color.getAlpha();
  349. StringBuilder sb = new StringBuilder("#");
  350. sb.append(hexDight[a >> 4 & 0xF]);
  351. sb.append(hexDight[a & 0xF]);
  352. sb.append(hexDight[r >> 4 & 0xF]);
  353. sb.append(hexDight[r & 0xF]);
  354. sb.append(hexDight[g >> 4 & 0xF]);
  355. sb.append(hexDight[g & 0xF]);
  356. sb.append(hexDight[b >> 4 & 0xF]);
  357. sb.append(hexDight[b & 0xF]);
  358. return sb.toString();
  359. }
  360. private void prepareColors() {
  361. // 从文件中读取颜色
  362. try {
  363. Scanner scanner = new Scanner(new File("resources/colors.txt"));
  364. while (scanner.hasNextLine()) {
  365. try {
  366. Color c = parseColorHex(scanner.nextLine().trim());
  367. if (c != null) {
  368. storedColors.add(c);
  369. }
  370. } catch (Exception e) {
  371. }
  372. }
  373. } catch (FileNotFoundException e) {
  374. e.printStackTrace();
  375. }
  376. // 创建一些默认的颜色
  377. final float delta = 0.2f;
  378. for (float r = 0; r <= 1.0; r += delta) {
  379. for (float g = 0; g <= 1.0; g += delta) {
  380. for (float b = 0; b <= 1.0; b += delta) {
  381. defaultColors.add(new Color(r, g, b));
  382. }
  383. }
  384. }
  385. }
  386. private int getHeightOfColorsRect(List<Color> li) {
  387. int row = (int) Math.ceil(li.size() / (float) columnSize);
  388. return row * colorRectWidth;
  389. }
  390. private void prepareColorsImage() {
  391. margin = padding.top;
  392. int w = columnSize * colorRectWidth;
  393. int h = getHeightOfColorsRect(storedColors) + getHeightOfColorsRect(defaultColors) + margin;
  394. int x = 0;
  395. int y = 0;
  396. colorsImageRect.setRect(padding.top, padding.top, w, h);
  397. colorsImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
  398. Graphics2D g2d = colorsImage.createGraphics();
  399. // 绘制用户存储的颜色
  400. for (int i = 0; i < storedColors.size(); ++i) {
  401. g2d.setPaint(storedColors.get(i));
  402. g2d.fillRect(x, y, colorRectWidth, colorRectHeight);
  403. x += colorRectWidth;
  404. if ((i + 1) % columnSize == 0) {
  405. x = 0;
  406. y += colorRectHeight;
  407. }
  408. }
  409. x = 0;
  410. y = getHeightOfColorsRect(storedColors) + margin;
  411. // 绘制默认的颜色
  412. for (int i = 0; i < defaultColors.size(); ++i) {
  413. g2d.setPaint(defaultColors.get(i));
  414. g2d.fillRect(x, y, colorRectWidth, colorRectHeight);
  415. x += colorRectWidth;
  416. if ((i + 1) % columnSize == 0) {
  417. x = 0;
  418. y += colorRectHeight;
  419. }
  420. }
  421. }
  422. private void prepareSize() {
  423. width = padding.left + colorsImage.getWidth() + padding.right;
  424. height = padding.top + colorsImage.getHeight() + padding.top + previewHeight + sliderHeight;
  425. }
  426. private void preparePreview() {
  427. int x = padding.left;
  428. int y = height - sliderHeight - previewHeight;
  429. int w = width - padding.left - padding.right;
  430. previewRect.setRect(x, y, w, previewHeight);
  431. }
  432. private void prepareSliders() {
  433. setLayout(null);
  434. int margin = 0; // slider之间的间隔,实际没必须
  435. int h = sliderHeight;
  436. int w = (width - padding.left - padding.right) / 4;
  437. int x = padding.left;
  438. int y = height - h + 2;
  439. redSlider.setBounds(x, y, w, h);
  440. x += w + margin;
  441. greenSlider.setBounds(x, y, w, h);
  442. x += w + margin;
  443. blueSlider.setBounds(x, y, w, h);
  444. x += w + margin;
  445. alphaSlider.setBounds(x, y, w, h);
  446. add(redSlider);
  447. add(greenSlider);
  448. add(blueSlider);
  449. add(alphaSlider);
  450. }
  451. @Override
  452. public Dimension getMinimumSize() {
  453. return new Dimension(width, height);
  454. }
  455. @Override
  456. public Dimension getMaximumSize() {
  457. return new Dimension(width, height);
  458. }
  459. @Override
  460. public Dimension getPreferredSize() {
  461. return new Dimension(width, height);
  462. }
  463. }
[html] view plain copy
 
  1. package gradient;
  2. import java.awt.Color;
  3. import java.awt.Graphics2D;
  4. import java.awt.geom.Rectangle2D;
  5. /**
  6. * 绘制Photoshop中透明色的效果.
  7. *
  8. * @author Biao
  9. *
  10. */
  11. public class TransparentPainter {
  12. public static void paint(Graphics2D g2d, Rectangle2D rect) {
  13. g2d.setClip(rect);
  14. int sx = (int) rect.getX();
  15. int sy = (int) rect.getY();
  16. int w = (int) rect.getWidth();
  17. int h = (int) rect.getHeight();
  18. Color color = Color.WHITE;
  19. Color color1 = Color.WHITE;
  20. Color color2 = Color.LIGHT_GRAY;
  21. int delta = 10;
  22. boolean odd = false;
  23. for (int y = sy; y <= h + sy; y += delta) {
  24. color = (odd) ? color1 : color2;
  25. for (int x = sx; x <= w + sx; x += delta) {
  26. g2d.setPaint(color);
  27. g2d.fillRect(x, y, w, h);
  28. color = (color == color1) ? color2 : color1;
  29. }
  30. odd = !odd;
  31. }
  32. g2d.setClip(null);
  33. }
  34. }
[html] view plain copy
 
  1. package gradient;
  2. import java.awt.geom.Point2D;
  3. public class GeometryUtil {
  4. // 两点之间的距离
  5. public static double distanceOfPoints(Point2D p1, Point2D p2) {
  6. double disX = p2.getX() - p1.getX();
  7. double disY = p2.getY() - p1.getY();
  8. double dis = Math.sqrt(disX * disX + disY * disY);
  9. return dis;
  10. }
  11. // 两点的中点
  12. public static Point2D middlePoint(Point2D p1, Point2D p2) {
  13. double x = (p1.getX() + p2.getX()) / 2;
  14. double y = (p1.getY() + p2.getY()) / 2;
  15. return new Point2D.Double(x, y);
  16. }
  17. // 在两点所在直线上,以从startPoint到endPoint为方向,离startPoint的距离disToStartPoint的点
  18. public static Point2D extentPoint(Point2D startPoint, Point2D endPoint, double disToStartPoint) {
  19. double disX = endPoint.getX() - startPoint.getX();
  20. double disY = endPoint.getY() - startPoint.getY();
  21. double dis = Math.sqrt(disX * disX + disY * disY);
  22. double sin = (endPoint.getY() - startPoint.getY()) / dis;
  23. double cos = (endPoint.getX() - startPoint.getX()) / dis;
  24. double deltaX = disToStartPoint * cos;
  25. double deltaY = disToStartPoint * sin;
  26. return new Point2D.Double(startPoint.getX() + deltaX, startPoint.getY() + deltaY);
  27. }
  28. }
上一篇:第五篇——C++实现四则运算


下一篇:seaJs学习笔记之javascript的依赖问题