java实现渐变效果工具
- 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);
- }
- }
- 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();
- }
- }
- 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);
- }
- }
- 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);
- }
- }
- 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);
- }
- }
java实现渐变效果工具的更多相关文章
- 细说Java主流日志工具库
概述 在项目开发中,为了跟踪代码的运行情况,常常要使用日志来记录信息. 在Java世界,有很多的日志工具库来实现日志功能,避免了我们重复造轮子. 我们先来逐一了解一下主流日志工具. java.util ...
- Java 性能分析工具 , 第 3 部分: Java Mission Control
引言 本文为 Java 性能分析工具系列文章第三篇,这里将介绍如何使用 Java 任务控制器 Java Mission Control 深入分析 Java 应用程序的性能,为程序开发人员在使用 Jav ...
- Java 性能分析工具 , 第 2 部分:Java 内置监控工具
引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工 ...
- HttpTool.java(在java tool util工具类中已存在) 暂保留
HttpTool.java 该类为java源生态的http 请求工具,不依赖第三方jar包 ,即插即用. package kingtool; import java.io.BufferedReader ...
- java keytool证书工具使用小结
java keytool证书工具使用小结 在Security编程中,有几种典型的密码交换信息文件格式: DER-encoded certificate: .cer, .crt PEM-encod ...
- [刘阳Java]_避开环境配置快速的使用Java的开发工具_第5讲
我们一般学习Java都应该遵循通过系统的命令工具来编译Java程序,然后对编译好Java程序进行运行,这个是非常好的习惯.但是随着后期学习Java技术的深入我们也得像Java的IDE工具屈服.所以,可 ...
- Java的各种工具类
下面是java的各种工具,包括获取时间和时间比较,检验集合和字符串是否为空和长度大小等等 1 import java.io.BufferedReader; import java.io.File; i ...
- Java XML解析工具 dom4j介绍及使用实例
Java XML解析工具 dom4j介绍及使用实例 dom4j介绍 dom4j的项目地址:http://sourceforge.net/projects/dom4j/?source=directory ...
- TDA - Thread Dump Analyzer (Java线程分析工具)
TDA - Thread Dump Analyzer (Java线程分析工具)http://automationqa.com/forum.php?mod=viewthread&tid=2351 ...
随机推荐
- LVS原理详解及部署之二:LVS原理详解(3种工作方式8种调度算法)
一.集群简介 什么是集群 计算机集群简称集群是一种计算机系统,它通过一组松散集成的计算机软件和/或硬件连接起来高度紧密地协作完成计算工作.在某种意义上,他们可以被看作是一 台计算机.集群系统中的单个计 ...
- Python学习 - 编写自己的ORM(2)
上一篇文章简单的实现了ORM(对象关系模型),这一篇文章主要实现简单的MySQL数据库操作. 想要操作数据库,首先要建立一个数据库连接.下面定义一个创建数据库连接的函数,得到一个连接叫做engine. ...
- "git add -A" is equivalent to "git add .; git add -u".
git add -A stages All git add . stages new and modified, without deleted git add -u stages modified ...
- 2016021801 - Java内存区域学习笔记
根据<深入理解java虚拟机>学习归纳整理学习笔记 程序计数器 用途:当前线程的字节码文件的行号指示器.(当前机场负责控制飞机降落的空管员:当前线程表示当前机场, 所执行的字节码等同于被等 ...
- servlet单例多线程
Servlet如何处理多个请求访问? Servlet容器默认是采用单实例多线程的方式处理多个请求的: 1.当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在 ...
- BZOJ2083: [Poi2010]Intelligence test
2083: [Poi2010]Intelligence test Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 241 Solved: 96[Sub ...
- 深入浅出Node.js (9) - 玩转进程
9.1 服务模型的变迁 9.1.1 石器时代:同步 9.1.2 青铜时代:复制进程 9.1.3 白银时代:多线程 9.1.4 黄金时代:事件驱动 9.2 多进程架构 9.2.1 创建子进程 9.2.2 ...
- 配置Myeclipse中的项目部署到服务器,报the selected server is enabled, but is not configured properly.
the selected server is enabled, but is not configured properly. deployment to it will not be permitt ...
- 如何配置jdk和tomcat 转
一.配置JDK1.解压JDK至D:\JDK1.5目录下(楼主可以自由选取目录).2.设置环境变量(右键我得电脑->属性->高级->环境变量),在系统变量中添加一个叫JAVA_HOME ...
- Win32中文件的操作
1 文件的创建或打开 HANDLE CreateFile( LPCTSTR lpFileName, //文件路径和名称 DWORD dwDesiredAccess, //访问方式,最常用的值 ...