在标签中“填充"Unicode 字符 [英] 'Fill' Unicode characters in labels

查看:28
本文介绍了在标签中“填充"Unicode 字符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 Swing 的标签中填充"Unicode 字符?

我正在尝试为我最近编写的国际象棋程序制作一个用户界面(棋子就像上面看到的那样).在其中,我使用 unicode 字符来表示我的棋子(u2654u265F).

问题如下:

当我将棋子 JLabel 的背景设置为类似白色时,整个标签被填充(在我的例子中,它是一个 50*50px 的白色正方形,字符在顶部).这导致我的作品看起来像瓷砖,而不仅仅是它们的图片.

当我将标签设置为不透明时,我只得到了一个千篇一律的国际象棋版本,而不是内部填充的版本.E.G.

有没有办法只填充字符?

如果不是,我想我会制作一个精灵表,但我喜欢这个,因为我可以使用国际象棋棋子的 toString() 方法作为标签.

代码

import java.awt.*;导入 javax.swing.*;导入 java.util.Random;类棋盘{static Font font = new Font("Sans-Serif", Font.PLAIN, 50);静态随机 rnd = 新随机();public static void addUnicodeCharToContainer(字符串 s,容器 c,布尔型 randomColor) {JLabel l = 新的 JLabel(s);l.setFont(字体);如果(随机颜色){int r = rnd.nextInt(255);int g = rnd.nextInt(255);int b = rnd.nextInt(255);l.setForeground(新颜色(r,g,b));l.setBackground(新颜色(255-r,255-g,255-b));l.setOpaque(true);}c.添加(l);}公共静态无效主(字符串 [] args){可运行 r = 新可运行(){@覆盖公共无效运行(){JPanel gui = new JPanel(new GridLayout(0,6,4,4));字符串 [] 件 = {"u2654","u2655","u2656","u2657","u2658","u2659","u265A"、"u265B"、"u265C"、"u265D"、"u265E"、"u265F"};对于(字符串件:件){addUnicodeCharToContainer(piece,gui,false);}对于(字符串件:件){addUnicodeCharToContainer(piece,gui,true);}JOptionPane.showMessageDialog(null, gui);}};SwingUtilities.invokeLater(r);}}

解决方案

这两行是通过Java-2D的魔法生成的.诀窍是:

  • 忽略黑色"棋子,因为我们的颜色实际上来自形状所包含的空间".这些在白棋子中更大.
  • 创建一个表示字符形状的 GlyphVector.这对于 Java-2D 中的进一步操作很重要.
  • 创建一个矩形图像的大小.
  • subtract() 从图像的形状中减去字符的形状.
  • 将改变后的形状分成多个区域.
  • 用背景颜色填充区域,但跳过从 0.0,0.0 开始的单个区域(代表我们需要透明的最外层区域).
  • 最后,使用轮廓颜色填充字符本身的形状.

代码

import java.awt.*;导入 java.awt.font.*;导入 java.awt.geom.*;导入 java.awt.image.BufferedImage;导入 javax.swing.*;导入 java.util.*;类棋盘{static Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 50);静态随机 rnd = 新随机();公共静态 ArrayListseparatorShapeIntoRegions(形状形状){ArrayList<形状>区域 = 新的 ArrayList();PathIterator pi = shape.getPathIterator(null);整数 ii = 0;GeneralPath gp = new GeneralPath();而 (!pi.isDone()) {double[] coords = new double[6];int pathSegmentType = pi.currentSegment(coords);intwindingRule = pi.getWindingRule();gp.setWindingRule(windingRule);如果(pathSegmentType == PathIterator.SEG_MOVETO){gp = new GeneralPath();gp.setWindingRule(windingRule);gp.moveTo(coords[0], coords[1]);System.out.println(ii++ + " 	" + coords[0] + "," + coords[1]);} else if (pathSegmentType == PathIterator.SEG_LINETO) {gp.lineTo(coords[0], coords[1]);} else if (pathSegmentType == PathIterator.SEG_QUADTO) {gp.quadTo(coords[0], coords[1], coords[2], coords[3]);} else if (pathSegmentType == PathIterator.SEG_CUBICTO) {gp.curveTo(坐标[0],坐标[1],坐标[2],坐标[3],坐标[4], 坐标[5]);} else if (pathSegmentType == PathIterator.SEG_CLOSE) {gp.closePath();地区.添加(新区域(gp));} 别的 {System.err.println("意外值!" + pathSegmentType);}pi.next();}返回区域;}public static void addColoredUnicodeCharToContainer(字符串 s,容器 c,颜色 bgColor、颜色轮廓颜色、布尔值 blackSquare) {int sz = font.getSize();BufferedImage bi = 新的 BufferedImage(sz, sz, BufferedImage.TYPE_INT_ARGB);Graphics2D g = bi.createGraphics();g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);FontRenderContext frc = g.getFontRenderContext();GlyphVector gv = font.createGlyphVector(frc, s);Rectangle2D box1 = gv.getVisualBounds();形状 shape1 = gv.getOutline();矩形 r = shape1.getBounds();System.out.println("形状矩形:" + r);int spaceX = sz - r.width;int spaceY = sz - r.height;AffineTransform trans = AffineTransform.getTranslateInstance(-r.x + (spaceX/2), -r.y + (spaceY/2));System.out.println("Box2D " + trans);形状 shapeCentered = trans.createTransformedShape(shape1);形状 imageShape = new Rectangle2D.Double(0, 0, sz, sz);区域 imageShapeArea = new Area(imageShape);区域 shapeArea = 新区域(shapeCentered);imageShapeArea.subtract(shapeArea);ArrayList<形状>区域=separateShapeIntoRegions(imageShapeArea);g.setStroke(new BasicStroke(1));对于(形状区域:区域){矩形 r1 = region.getBounds();如果 (r1.getX() <0.001 && r1.getY() <0.001) {} 别的 {g.setColor(bgColor);g.填充(区域);}}g.setColor(outlineColor);g.fill(shapeArea);g.dispose();JLabel l = new JLabel(new ImageIcon(bi), JLabel.CENTER);颜色 bg = (blackSquare ? Color.BLACK : Color.WHITE);l.setBackground(bg);l.setOpaque(true);c.添加(l);}公共静态无效主(字符串 [] args){可运行 r = 新可运行(){@覆盖公共无效运行(){JPanel gui = new JPanel(new GridLayout(0, 6, 4, 4));字符串 [] 件 = {u2654"、u2655"、u2656"、u2657"、u2658"、u2659"};布尔 blackSquare = false;对于(字符串件:件){addColoredUnicodeCharToContainer(片, gui,新颜色(203,203,197),颜色.DARK_GRAY,黑方);blackSquare = !blackSquare;}blackSquare = !blackSquare;对于(字符串件:件){addColoredUnicodeCharToContainer(片, gui,新颜色(192,142,60),颜色.DARK_GRAY,黑方);blackSquare = !blackSquare;}JOptionPane.showMessageDialog(null, gui);}};SwingUtilities.invokeLater(r);}}

棋盘

这可能是 (11.64Kb).

<块引用>

(13.44Kb).

<块引用>

国际象棋棋盘代码精灵套装

import java.awt.*;导入 java.awt.font.*;导入 java.awt.geom.*;导入 java.awt.image.BufferedImage;导入 javax.swing.*;导入 javax.swing.border.*;导入 java.io.*;导入 javax.imageio.ImageIO;导入 java.util.*;导入 java.util.logging.*;类棋盘{/*** 国际象棋棋子的 Unicode.*/静态最终字符串 [] 件 = {u2654"、u2655"、u2656"、u2657"、u2658"、u2659"};静态最终 int KING = 0, QUEEN = 1, CASTLE = 2,主教 = 3,骑士 = 4,典当 = 5;public static final int[] order = new int[]{城堡,骑士,主教,女王,国王,主教,骑士,城堡};/** 颜色..*/public static final Color outlineColor = Color.DARK_GRAY;public static final Color[]pieceColors = {新颜色(203, 203, 197), 新颜色(192, 142, 60)};静态最终 int 白色 = 0,黑色 = 1;/** 字体.图像使用字体 sizeXsize.*/static Font font = new Font("Sans-Serif", Font.PLAIN, 64);公共静态 ArrayListseparatorShapeIntoRegions(形状形状){ArrayList<形状>区域 = 新的 ArrayList();PathIterator pi = shape.getPathIterator(null);整数 ii = 0;GeneralPath gp = new GeneralPath();而 (!pi.isDone()) {double[] coords = new double[6];int pathSegmentType = pi.currentSegment(coords);intwindingRule = pi.getWindingRule();gp.setWindingRule(windingRule);如果(pathSegmentType == PathIterator.SEG_MOVETO){gp = new GeneralPath();gp.setWindingRule(windingRule);gp.moveTo(coords[0], coords[1]);} else if (pathSegmentType == PathIterator.SEG_LINETO) {gp.lineTo(coords[0], coords[1]);} else if (pathSegmentType == PathIterator.SEG_QUADTO) {gp.quadTo(coords[0], coords[1], coords[2], coords[3]);} else if (pathSegmentType == PathIterator.SEG_CUBICTO) {gp.curveTo(坐标[0],坐标[1],坐标[2],坐标[3],坐标[4], 坐标[5]);} else if (pathSegmentType == PathIterator.SEG_CLOSE) {gp.closePath();地区.添加(新区域(gp));} 别的 {System.err.println("意外值!" + pathSegmentType);}pi.next();}返回区域;}公共静态 BufferedImage getImageForChessPiece(整块,整边,布尔梯度){int sz = font.getSize();BufferedImage bi = 新的 BufferedImage(sz, sz, BufferedImage.TYPE_INT_ARGB);Graphics2D g = bi.createGraphics();g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE);g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);FontRenderContext frc = g.getFontRenderContext();GlyphVector gv = font.createGlyphVector(frc,pieces[piece]);Rectangle2D box1 = gv.getVisualBounds();形状 shape1 = gv.getOutline();矩形 r = shape1.getBounds();int spaceX = sz - r.width;int spaceY = sz - r.height;AffineTransform trans = AffineTransform.getTranslateInstance(-r.x + (spaceX/2), -r.y + (spaceY/2));形状 shapeCentered = trans.createTransformedShape(shape1);形状 imageShape = new Rectangle2D.Double(0, 0, sz, sz);区域 imageShapeArea = new Area(imageShape);区域 shapeArea = 新区域(shapeCentered);imageShapeArea.subtract(shapeArea);ArrayList<形状>区域=separateShapeIntoRegions(imageShapeArea);g.setStroke(new BasicStroke(1));g.setColor(pieceColors[side]);颜色 baseColor =pieceColors[side];如果(梯度){颜色 c1 = baseColor.brighter();颜色 c2 = 基色;GradientPaint gp = new GradientPaint(sz/2-(r.width/4), sz/2-(r.height/4), c1,sz/2+(r.width/4), sz/2+(r.height/4), c2,错误的);g.setPaint(gp);} 别的 {g.setColor(baseColor);}对于(形状区域:区域){矩形 r1 = region.getBounds();如果 (r1.getX() <0.001 && r1.getY() <0.001) {} 别的 {g.填充(区域);}}g.setColor(outlineColor);g.fill(shapeArea);g.dispose();返回bi;}public static void addColoredUnicodeCharToContainer(集装箱 c,整块,内部,彩色背景,布尔梯度){JLabel l = 新 JLabel(new ImageIcon(getImageForChessPiece(piece, side, gradient)),JLabel.CENTER);l.setBackground(bg);l.setOpaque(true);c.添加(l);}public static void addPiecesToContainer(集装箱 c,int intialSquareColor,内部,int[] 件,布尔梯度){对于(整数件:件){addColoredUnicodeCharToContainer(c、片、边、intialSquareColor++%2 == 黑色?Color.BLACK : Color.WHITE,坡度);}}public static void addPiecesToContainer(集装箱 c,彩色背景,内部,int[] 件,布尔梯度){对于(整数件:件){addColoredUnicodeCharToContainer(c、片、边、背景、渐变);}}public static void addBlankLabelRow(Container c, int initialSquareColor) {对于 (int ii = 0; ii <8; ii++) {JLabel l = new JLabel();颜色 bg = (initialSquareColor++ % 2 == BLACK?Color.BLACK : Color.WHITE);l.setBackground(bg);l.setOpaque(true);c.添加(l);}}公共静态无效主(字符串 [] args){最终 int[] pawnRow = 新 int[]{典当,典当,典当,典当,典当,典当,典当,典当};可运行 r = 新可运行(){@覆盖公共无效运行(){int 渐变 = JOptionPane.showConfirmDialog(null, "使用渐变填充颜色?");布尔渐变填充 = 渐变 == JOptionPane.OK_OPTION;JPanel gui = new JPanel(new GridLayout(0, 8, 0, 0));gui.setBorder(新斜角边框(BevelBorder.LOWERED,Color.GRAY.brighter(), Color.GRAY,Color.GRAY.darker(), Color.GRAY));//设置棋盘addPiecesToContainer(gui, WHITE, BLACK, order, gradientFill);addPiecesToContainer(gui, BLACK, BLACK, pawnRow, gradientFill);addBlankLabelRow(gui, WHITE);addBlankLabelRow(gui, 黑色);addBlankLabelRow(gui, WHITE);addBlankLabelRow(gui, 黑色);addPiecesToContainer(gui, WHITE, WHITE, pawnRow, gradientFill);addPiecesToContainer(gui, BLACK, WHITE, order, gradientFill);JOptionPane.showMessageDialog(空值,贵,棋盘",JOptionPane.INFORMATION_MESSAGE);JPanel tileSet = new JPanel(new GridLayout(0, 6, 0, 0));tileSet.setOpaque(false);int[] tileSetOrder = 新的 int[]{国王、王后、城堡、骑士、主教、典当};addPiecesToContainer(瓷砖集,新颜色(0, 0, 0, 0),黑色的,瓷砖集订单,渐变填充);addPiecesToContainer(瓷砖集,新颜色(0, 0, 0, 0),白色的,瓷砖集订单,渐变填充);int 结果 = JOptionPane.showConfirmDialog(空值,瓷砖集,保存这个图块集?",JOptionPane.OK_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE);如果(结果 == JOptionPane.OK_OPTION){BufferedImage bi = 新的 BufferedImage(tileSet.getWidth(),tileSet.getHeight(),BufferedImage.TYPE_INT_ARGB);图形 g = bi.createGraphics();tileSet.paint(g);g.dispose();字符串渐变字符串 = 渐变填充?渐变":固体";文件 f = 新文件("chess-pieces-tileset-" + gradientString + ".png");尝试 {ImageIO.write(bi, "png", f);Desktop.getDesktop().open(f);} catch (IOException ex) {Logger.getLogger(ChessBoard.class.getName()).log(Level.SEVERE, null, ex);}}}};SwingUtilities.invokeLater(r);}}

另见

  • 根据 GlyphVector 代码开发,如.

How to 'fill' Unicode characters in labels in Swing?

I'm trying to make a user interface for the chess program I've recently programmed (with chess pieces something like seen above). In it I'm using unicode characters to represent my chess pieces (u2654 through u265F).

The problem is as follows:

When I set the background of my chess piece JLabel to something like white, the entire label is filled (in my case it's a 50*50px square of white with the character on top). This leads to my pieces looking like tiles instead of just their pictures.

When I set the label to opaque, I just get a cookie cutter version of my chess piece, not one with its insides filled. E.G.

Is there a way to fill only the character?

If not I guess I'll make a sprite sheet but I like this because I can use the chess pieces' toString() methods for the labels.

Code

import java.awt.*;
import javax.swing.*;
import java.util.Random;

class ChessBoard {

    static Font font = new Font("Sans-Serif", Font.PLAIN, 50);
    static Random rnd = new Random();

    public static void addUnicodeCharToContainer(
        String s, Container c, boolean randomColor) {

        JLabel l = new JLabel(s);
        l.setFont(font);
        if (randomColor) {
            int r = rnd.nextInt(255);
            int g = rnd.nextInt(255);
            int b = rnd.nextInt(255);

            l.setForeground(new Color(r,g,b));
            l.setBackground(new Color(255-r,255-g,255-b));
            l.setOpaque(true);
        }
        c.add(l);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                JPanel gui = new JPanel(new GridLayout(0,6,4,4));

                String[] pieces = {
                    "u2654","u2655","u2656","u2657","u2658","u2659",
                    "u265A","u265B","u265C","u265D","u265E","u265F"
                };

                for (String piece : pieces) {
                    addUnicodeCharToContainer(piece,gui,false);
                }
                for (String piece : pieces) {
                    addUnicodeCharToContainer(piece,gui,true);
                }

                JOptionPane.showMessageDialog(null, gui);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

解决方案

The two rows are generated through the sorcery of Java-2D. The trick is to:

  • Ignore the 'black' chess pieces on the basis that our color is actually coming from 'the spaces contained by the shape'. Those are larger in the white chess pieces.
  • Create a GlyphVector that represents the shape of the character. This is important for further operations in Java-2D.
  • Create a Rectangle the size of the image.
  • subtract() the shape of the character from the shape of the image.
  • Break that altered shape into regions.
  • Fill the regions with the background color, but skip the single region that starts at 0.0,0.0 (representing the outermost region which we need transparent).
  • Finally, fill the shape of the character itself using the outline color.

Code

import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.util.*;

class ChessBoard {

    static Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 50);
    static Random rnd = new Random();

    public static ArrayList<Shape> separateShapeIntoRegions(Shape shape) {
        ArrayList<Shape> regions = new ArrayList<Shape>();

        PathIterator pi = shape.getPathIterator(null);
        int ii = 0;
        GeneralPath gp = new GeneralPath();
        while (!pi.isDone()) {
            double[] coords = new double[6];
            int pathSegmentType = pi.currentSegment(coords);
            int windingRule = pi.getWindingRule();
            gp.setWindingRule(windingRule);
            if (pathSegmentType == PathIterator.SEG_MOVETO) {
                gp = new GeneralPath();
                gp.setWindingRule(windingRule);
                gp.moveTo(coords[0], coords[1]);
                System.out.println(ii++ + " 	" + coords[0] + "," + coords[1]);
            } else if (pathSegmentType == PathIterator.SEG_LINETO) {
                gp.lineTo(coords[0], coords[1]);
            } else if (pathSegmentType == PathIterator.SEG_QUADTO) {
                gp.quadTo(coords[0], coords[1], coords[2], coords[3]);
            } else if (pathSegmentType == PathIterator.SEG_CUBICTO) {
                gp.curveTo(
                        coords[0], coords[1],
                        coords[2], coords[3],
                        coords[4], coords[5]);
            } else if (pathSegmentType == PathIterator.SEG_CLOSE) {
                gp.closePath();
                regions.add(new Area(gp));
            } else {
                System.err.println("Unexpected value! " + pathSegmentType);
            }

            pi.next();
        }

        return regions;
    }

    public static void addColoredUnicodeCharToContainer(
            String s, Container c,
            Color bgColor, Color outlineColor, boolean blackSquare) {

        int sz = font.getSize();
        BufferedImage bi = new BufferedImage(
                sz, sz, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = bi.createGraphics();
        g.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(
                RenderingHints.KEY_DITHERING,
                RenderingHints.VALUE_DITHER_ENABLE);
        g.setRenderingHint(
                RenderingHints.KEY_ALPHA_INTERPOLATION,
                RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

        FontRenderContext frc = g.getFontRenderContext();
        GlyphVector gv = font.createGlyphVector(frc, s);
        Rectangle2D box1 = gv.getVisualBounds();

        Shape shape1 = gv.getOutline();
        Rectangle r = shape1.getBounds();
        System.out.println("shape rect: " + r);
        int spaceX = sz - r.width;
        int spaceY = sz - r.height;
        AffineTransform trans = AffineTransform.getTranslateInstance(
                -r.x + (spaceX / 2), -r.y + (spaceY / 2));
        System.out.println("Box2D " + trans);

        Shape shapeCentered = trans.createTransformedShape(shape1);

        Shape imageShape = new Rectangle2D.Double(0, 0, sz, sz);
        Area imageShapeArea = new Area(imageShape);
        Area shapeArea = new Area(shapeCentered);
        imageShapeArea.subtract(shapeArea);
        ArrayList<Shape> regions = separateShapeIntoRegions(imageShapeArea);
        g.setStroke(new BasicStroke(1));
        for (Shape region : regions) {
            Rectangle r1 = region.getBounds();
            if (r1.getX() < 0.001 && r1.getY() < 0.001) {
            } else {
                g.setColor(bgColor);
                g.fill(region);
            }
        }
        g.setColor(outlineColor);
        g.fill(shapeArea);
        g.dispose();

        JLabel l = new JLabel(new ImageIcon(bi), JLabel.CENTER);
        Color bg = (blackSquare ? Color.BLACK : Color.WHITE);
        l.setBackground(bg);
        l.setOpaque(true);
        c.add(l);
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                JPanel gui = new JPanel(new GridLayout(0, 6, 4, 4));

                String[] pieces = {
                    "u2654", "u2655", "u2656", "u2657", "u2658", "u2659"
                };

                boolean blackSquare = false;
                for (String piece : pieces) {
                    addColoredUnicodeCharToContainer(
                            piece, gui,
                            new Color(203,203,197),
                            Color.DARK_GRAY,
                            blackSquare);
                            blackSquare = !blackSquare;
                }
                            blackSquare = !blackSquare;
                for (String piece : pieces) {
                    addColoredUnicodeCharToContainer(
                            piece, gui,
                            new Color(192,142,60),
                            Color.DARK_GRAY,
                            blackSquare);
                            blackSquare = !blackSquare;
                }

                JOptionPane.showMessageDialog(null, gui);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

Chess Board

This is what it might look like as a Chess Board (22.81 Kb).

Sprite sets

Sprite sets of chess pieces (64x64 pixel) rendered from Unicode characters - as a PNG with transparent BG. Each has 6 columns for the pieces x 2 rows for the opponents (total size 384x128 pixels).

Chess pieces with solid fill (bronze/pewter) (11.64Kb).

Chess pieces with gradient fill (gold/silver) (13.61Kb).

Chess pieces with gradient fill (darker cyan/magenta) (13.44Kb).

Code for Chess Board & Sprite Set

import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.*;

import java.io.*;
import javax.imageio.ImageIO;
import java.util.*;
import java.util.logging.*;

class ChessBoard {

    /**
     * Unicodes for chess pieces.
     */
    static final String[] pieces = {
        "u2654", "u2655", "u2656", "u2657", "u2658", "u2659"
    };
    static final int KING = 0, QUEEN = 1, CASTLE = 2,
            BISHOP = 3, KNIGHT = 4, PAWN = 5;
    public static final int[] order = new int[]{
        CASTLE, KNIGHT, BISHOP, QUEEN, KING, BISHOP, KNIGHT, CASTLE
    };

    /*
     * Colors..
     */
    public static final Color outlineColor = Color.DARK_GRAY;
    public static final Color[] pieceColors = {
        new Color(203, 203, 197), new Color(192, 142, 60)
    };
    static final int WHITE = 0, BLACK = 1;

    /*
     * Font. The images use the font sizeXsize.
     */
    static Font font = new Font("Sans-Serif", Font.PLAIN, 64);

    public static ArrayList<Shape> separateShapeIntoRegions(Shape shape) {
        ArrayList<Shape> regions = new ArrayList<Shape>();

        PathIterator pi = shape.getPathIterator(null);
        int ii = 0;
        GeneralPath gp = new GeneralPath();
        while (!pi.isDone()) {
            double[] coords = new double[6];
            int pathSegmentType = pi.currentSegment(coords);
            int windingRule = pi.getWindingRule();
            gp.setWindingRule(windingRule);
            if (pathSegmentType == PathIterator.SEG_MOVETO) {
                gp = new GeneralPath();
                gp.setWindingRule(windingRule);
                gp.moveTo(coords[0], coords[1]);
            } else if (pathSegmentType == PathIterator.SEG_LINETO) {
                gp.lineTo(coords[0], coords[1]);
            } else if (pathSegmentType == PathIterator.SEG_QUADTO) {
                gp.quadTo(coords[0], coords[1], coords[2], coords[3]);
            } else if (pathSegmentType == PathIterator.SEG_CUBICTO) {
                gp.curveTo(
                        coords[0], coords[1],
                        coords[2], coords[3],
                        coords[4], coords[5]);
            } else if (pathSegmentType == PathIterator.SEG_CLOSE) {
                gp.closePath();
                regions.add(new Area(gp));
            } else {
                System.err.println("Unexpected value! " + pathSegmentType);
            }

            pi.next();
        }

        return regions;
    }

    public static BufferedImage getImageForChessPiece(
            int piece, int side, boolean gradient) {
        int sz = font.getSize();
        BufferedImage bi = new BufferedImage(
                sz, sz, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = bi.createGraphics();
        g.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(
                RenderingHints.KEY_DITHERING,
                RenderingHints.VALUE_DITHER_ENABLE);
        g.setRenderingHint(
                RenderingHints.KEY_ALPHA_INTERPOLATION,
                RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

        FontRenderContext frc = g.getFontRenderContext();
        GlyphVector gv = font.createGlyphVector(frc, pieces[piece]);
        Rectangle2D box1 = gv.getVisualBounds();

        Shape shape1 = gv.getOutline();
        Rectangle r = shape1.getBounds();
        int spaceX = sz - r.width;
        int spaceY = sz - r.height;
        AffineTransform trans = AffineTransform.getTranslateInstance(
                -r.x + (spaceX / 2), -r.y + (spaceY / 2));

        Shape shapeCentered = trans.createTransformedShape(shape1);

        Shape imageShape = new Rectangle2D.Double(0, 0, sz, sz);
        Area imageShapeArea = new Area(imageShape);
        Area shapeArea = new Area(shapeCentered);
        imageShapeArea.subtract(shapeArea);
        ArrayList<Shape> regions = separateShapeIntoRegions(imageShapeArea);
        g.setStroke(new BasicStroke(1));
        g.setColor(pieceColors[side]);
        Color baseColor = pieceColors[side];
        if (gradient) {
            Color c1 = baseColor.brighter();
            Color c2 = baseColor;
            GradientPaint gp = new GradientPaint(
                    sz/2-(r.width/4), sz/2-(r.height/4), c1, 
                    sz/2+(r.width/4), sz/2+(r.height/4), c2, 
                    false);
            g.setPaint(gp);
        } else {
            g.setColor(baseColor);
        }

        for (Shape region : regions) {
            Rectangle r1 = region.getBounds();
            if (r1.getX() < 0.001 && r1.getY() < 0.001) {
            } else {
                g.fill(region);
            }
        }
        g.setColor(outlineColor);
        g.fill(shapeArea);
        g.dispose();

        return bi;
    }

    public static void addColoredUnicodeCharToContainer(
            Container c,
            int piece,
            int side,
            Color bg,
            boolean gradient) {

        JLabel l = new JLabel(
                new ImageIcon(getImageForChessPiece(piece, side, gradient)),
                JLabel.CENTER);
        l.setBackground(bg);
        l.setOpaque(true);
        c.add(l);
    }

    public static void addPiecesToContainer(
            Container c,
            int intialSquareColor,
            int side,
            int[] pieces,
            boolean gradient) {

        for (int piece : pieces) {
            addColoredUnicodeCharToContainer(
                    c, piece, side,
                    intialSquareColor++%2 == BLACK ? Color.BLACK : Color.WHITE,
                    gradient);
        }
    }

    public static void addPiecesToContainer(
            Container c,
            Color bg,
            int side,
            int[] pieces,
            boolean gradient) {

        for (int piece : pieces) {
            addColoredUnicodeCharToContainer(
                    c, piece, side, bg, gradient);
        }
    }

    public static void addBlankLabelRow(Container c, int initialSquareColor) {
        for (int ii = 0; ii < 8; ii++) {
            JLabel l = new JLabel();
            Color bg = (initialSquareColor++ % 2 == BLACK
                    ? Color.BLACK : Color.WHITE);
            l.setBackground(bg);
            l.setOpaque(true);
            c.add(l);
        }
    }

    public static void main(String[] args) {
        final int[] pawnRow = new int[]{
            PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN, PAWN
        };
        Runnable r = new Runnable() {

            @Override
            public void run() {
                int gradient = JOptionPane.showConfirmDialog(
                        null, "Use gradient fille color?");
                boolean gradientFill = gradient == JOptionPane.OK_OPTION;
                JPanel gui = new JPanel(new GridLayout(0, 8, 0, 0));
                gui.setBorder(new BevelBorder(
                        BevelBorder.LOWERED,
                        Color.GRAY.brighter(), Color.GRAY,
                        Color.GRAY.darker(), Color.GRAY));
                // set up a chess board
                addPiecesToContainer(gui, WHITE, BLACK, order, gradientFill);
                addPiecesToContainer(gui, BLACK, BLACK, pawnRow, gradientFill);

                addBlankLabelRow(gui, WHITE);
                addBlankLabelRow(gui, BLACK);
                addBlankLabelRow(gui, WHITE);
                addBlankLabelRow(gui, BLACK);

                addPiecesToContainer(gui, WHITE, WHITE, pawnRow, gradientFill);
                addPiecesToContainer(gui, BLACK, WHITE, order, gradientFill);

                JOptionPane.showMessageDialog(
                        null,
                        gui,
                        "Chessboard",
                        JOptionPane.INFORMATION_MESSAGE);

                JPanel tileSet = new JPanel(new GridLayout(0, 6, 0, 0));
                tileSet.setOpaque(false);
                int[] tileSetOrder = new int[]{
                    KING, QUEEN, CASTLE, KNIGHT, BISHOP, PAWN
                };
                addPiecesToContainer(
                        tileSet,
                        new Color(0, 0, 0, 0),
                        BLACK,
                        tileSetOrder, 
                        gradientFill);
                addPiecesToContainer(
                        tileSet,
                        new Color(0, 0, 0, 0),
                        WHITE,
                        tileSetOrder, 
                        gradientFill);
                int result = JOptionPane.showConfirmDialog(
                        null,
                        tileSet,
                        "Save this tileset?",
                        JOptionPane.OK_CANCEL_OPTION,
                        JOptionPane.QUESTION_MESSAGE);
                if (result == JOptionPane.OK_OPTION) {
                    BufferedImage bi = new BufferedImage(
                            tileSet.getWidth(),
                            tileSet.getHeight(),
                            BufferedImage.TYPE_INT_ARGB);
                    Graphics g = bi.createGraphics();
                    tileSet.paint(g);
                    g.dispose();

                    String gradientString = gradientFill ? "gradient" : "solid";
                    File f = new File(
                            "chess-pieces-tileset-" + gradientString + ".png");
                    try {
                        ImageIO.write(bi, "png", f);
                        Desktop.getDesktop().open(f);
                    } catch (IOException ex) {
                        Logger.getLogger(
                                ChessBoard.class.getName()).log(
                                Level.SEVERE, null, ex);
                    }
                }
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

See also

  • Developed out of the GlyphVector code as seen in this answer.

这篇关于在标签中“填充"Unicode 字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆