问题描述
如何在 Swing 的标签中填充"Unicode 字符?
我正在尝试为我最近编写的国际象棋程序制作用户界面(与上图类似的棋子).在其中,我使用 unicode 字符来表示我的棋子(u2654
到 u265F
).
问题如下:
当我将我的棋子 JLabel
的背景设置为白色时,整个标签都会被填充(在我的例子中,它是一个 50*50 像素的白色正方形,顶部有字符).这导致我的作品看起来像瓷砖,而不仅仅是它们的图片.
当我将标签设置为不透明时,我只是得到了我的棋子的千篇一律的版本,而不是内部填充的棋子.例如
有没有办法只填充字符?
如果不是,我想我会制作一个精灵表,但我喜欢这个,因为我可以使用棋子的 toString()
方法作为标签.
代码
import java.awt.*;导入 javax.swing.*;导入 java.util.Random;类棋盘{static Font font = new Font("Sans-Serif", Font.PLAIN, 50);静态随机 rnd = new Random();公共静态无效添加UnicodeCharToContainer(字符串 s,容器 c,布尔随机颜色){JLabel l = 新的 JLabel(s);l.setFont(字体);如果(随机颜色){int r = rnd.nextInt(255);诠释 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.add(l);}公共静态无效主(字符串 [] args){可运行 r = new Runnable() {@覆盖公共无效运行(){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.*;类棋盘{静态字体字体=新字体(Font.SANS_SERIF,Font.PLAIN,50);静态随机 rnd = new Random();公共静态数组列表<形状>单独的ShapeIntoRegions(形状形状){数组列表<形状>区域 = 新的 ArrayList<形状>();PathIterator pi = shape.getPathIterator(null);int ii = 0;GeneralPath gp = new GeneralPath();而(!pi.isDone()){双[]坐标=新双[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(坐标[0],坐标[1]);System.out.println(ii++ + " " + coords[0] + "," + coords[1]);} else if (pathSegmentType == PathIterator.SEG_LINETO) {gp.lineTo(坐标[0],坐标[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();region.add(新区域(gp));} 别的 {System.err.println("意外的值!" + pathSegmentType);}pi.next();}返回区域;}公共静态无效 addColoredUnicodeCharToContainer(字符串 s,容器 c,颜色 bgColor, 颜色 outlineColor, boolean 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 = new Area(shapeCentered);imageShapeArea.subtract(shapeArea);数组列表<形状>区域 = 单独的ShapeIntoRegions(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.add(l);}公共静态无效主(字符串 [] args){可运行 r = new Runnable() {@覆盖公共无效运行(){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[]{城堡,骑士,主教,女王,国王,主教,骑士,城堡};/** 颜色..*/公共静态最终颜色 outlineColor = Color.DARK_GRAY;公共静态最终颜色 []pieceColors = {新颜色(203、203、197)、新颜色(192、142、60)};静态最终 int 白色 = 0,黑色 = 1;/** 字体.图像使用字体 sizeXsize.*/static Font font = new Font("Sans-Serif", Font.PLAIN, 64);公共静态数组列表<形状>单独的ShapeIntoRegions(形状形状){数组列表<形状>区域 = 新的 ArrayList<形状>();PathIterator pi = shape.getPathIterator(null);int ii = 0;GeneralPath gp = new GeneralPath();而(!pi.isDone()){双[]坐标=新双[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(坐标[0],坐标[1]);} else if (pathSegmentType == PathIterator.SEG_LINETO) {gp.lineTo(坐标[0],坐标[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();region.add(新区域(gp));} 别的 {System.err.println("意外的值!" + pathSegmentType);}pi.next();}返回区域;}公共静态 BufferedImage getImageForChessPiece(int 片,int 边,布尔梯度){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 = new Area(shapeCentered);imageShapeArea.subtract(shapeArea);数组列表<形状>区域 = 单独的ShapeIntoRegions(imageShapeArea);g.setStroke(new BasicStroke(1));g.setColor(pieceColors[side]);颜色 baseColor = pieceColors[side];如果(梯度){颜色 c1 = baseColor.brighter();颜色 c2 = baseColor;GradientPaint gp = 新的 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();返回双;}公共静态无效 addColoredUnicodeCharToContainer(容器 c,整数块,整数边,颜色 bg,布尔梯度){JLabel l = 新的 JLabel(new ImageIcon(getImageForChessPiece(piece, side, gradient)),JLabel.CENTER);l.setBackground(bg);l.setOpaque(true);c.add(l);}公共静态无效 addPiecesToContainer(容器 c,int intialSquareColor,整数边,int[] 件,布尔梯度){对于(int片:片){addColoredUnicodeCharToContainer(c, 片, 边,intialSquareColor++%2 == 黑色?颜色.黑色:颜色.白色,坡度);}}公共静态无效 addPiecesToContainer(容器 c,颜色 bg,整数边,int[] 件,布尔梯度){对于(int片:片){addColoredUnicodeCharToContainer(c、片、边、bg、渐变);}}公共静态无效addBlankLabelRow(容器c,int initialSquareColor){for (int ii = 0; ii < 8; ii++) {JLabel l = 新的 JLabel();颜色 bg = (initialSquareColor++ % 2 == 黑色?颜色.黑色:颜色.白色);l.setBackground(bg);l.setOpaque(true);c.add(l);}}公共静态无效主(字符串 [] args){最终的 int[] pawnRow = 新的 int[]{典当,典当,典当,典当,典当,典当,典当,典当};可运行 r = new Runnable() {@覆盖公共无效运行(){int 渐变 = JOptionPane.showConfirmDialog(null, "使用渐变填充颜色?");布尔梯度填充 = 梯度 == JOptionPane.OK_OPTION;JPanel gui = new JPanel(new GridLayout(0, 8, 0, 0));gui.setBorder(新的 BevelBorder(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, 白色);addBlankLabelRow(gui, 黑色);addBlankLabelRow(gui, 白色);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 = new int[]{国王、王后、城堡、骑士、主教、典当};addPiecesToContainer(瓦片集,新颜色(0, 0, 0, 0),黑色的,tileSetOrder,渐变填充);addPiecesToContainer(瓦片集,新颜色(0, 0, 0, 0),白色的,tileSetOrder,渐变填充);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) {记录器.getLogger(ChessBoard.class.getName()).log(Level.SEVERE, null, ex);}}}};SwingUtilities.invokeLater(r);}}
另见
- 由 在 GitHub.
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).
CodeforChessBoard&SpriteSet
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.
- Resulted in UGlys - Unicode Glyphs at GitHub.
这篇关于“填充"标签中的 Unicode 字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!