如何在AWT中围绕文本绘制轮廓?
如何在AWT中的任何文本周围绘制轮廓,类似于这张图片?
两个例子
-
字体和AffineTransform
-
Font,TextLayout和AffineTransform
这个绘制的输出将是BufferedImage
,对于AWT组件使用方法paint()
,对于Swing JComponents是否有paintComponet()
此外,从评论中链接的代码:
不知道你现在是如何绘制文本的,但是你能做到的一种方法是使用BufferedImage作为你正在绘制的任何东西的叠加层。
- 使用您想要绘制的字符串和字体的尺寸创建BufferedImage(请查看FontMetrics类)。
- 用透明度填充BufferedImage。
- 用你想要的任何颜色将你的字符串画到BufferedImage上。
- 迭代BufferedImage中的每个像素,看看它与文本颜色的像素有多远。 如果它在一定距离内,则将该像素绘制为黑色,如果距离文本的颜色更远,则可能更透明。 当然,如果像素的颜色与文本颜色相同,则忽略它。
- 将BufferedImage绘制到您正在绘制的任何内容上。
编辑
可能已经存在已经执行此操作的库,但如果我必须从头开始编写代码,那么我就是这样做的。
请尝试以下方法:
public void paintTextWithOutline(Graphics g) { String text = "some text"; Color outlineColor = Color.white; Color fillColor = Color.black; BasicStroke outlineStroke = new BasicStroke(2.0f); if (g instanceof Graphics2D) { Graphics2D g2 = (Graphics2D) g; // remember original settings Color originalColor = g2.getColor(); Stroke originalStroke = g2.getStroke(); RenderingHints originalHints = g2.getRenderingHints(); // create a glyph vector from your text GlyphVector glyphVector = getFont().createGlyphVector(g2.getFontRenderContext(), text); // get the shape object Shape textShape = glyphVector.getOutline(); // activate anti aliasing for text rendering (if you want it to look nice) g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2.setColor(outlineColor); g2.setStroke(outlineStroke); g2.draw(textShape); // draw outline g2.setColor(fillColor); g2.fill(textShape); // fill the shape // reset to original settings after painting g2.setColor(originalColor); g2.setStroke(originalStroke); g2.setRenderingHints(originalHints); } }
一些最愚蠢的解决方法: – 两次相同的单词,但其中一个是黑色,另一个是白色,白色在黑色上面,你可能会得到类似的东西。 – 找到类似于示例的字体,然后使用它。
这是一个hacky的例子。 它不像其他人那么复杂,但它更容易理解,它的行为就像一个JLabel。
public class OutlineLabel extends JLabel { private Color outlineColor = Color.WHITE; private boolean isPaintingOutline = false; private boolean forceTransparent = false; public OutlineLabel() { super(); } public OutlineLabel(String text) { super(text); } public OutlineLabel(String text, int horizontalAlignment) { super(text, horizontalAlignment); } public Color getOutlineColor() { return outlineColor; } public void setOutlineColor(Color outlineColor) { this.outlineColor = outlineColor; this.invalidate(); } @Override public Color getForeground() { if ( isPaintingOutline ) { return outlineColor; } else { return super.getForeground(); } } @Override public boolean isOpaque() { if ( forceTransparent ) { return false; } else { return super.isOpaque(); } } @Override public void paint(Graphics g) { String text = getText(); if ( text == null || text.length() == 0 ) { super.paint(g); return; } // 1 2 3 // 8 9 4 // 7 6 5 if ( isOpaque() ) super.paint(g); forceTransparent = true; isPaintingOutline = true; g.translate(-1, -1); super.paint(g); // 1 g.translate( 1, 0); super.paint(g); // 2 g.translate( 1, 0); super.paint(g); // 3 g.translate( 0, 1); super.paint(g); // 4 g.translate( 0, 1); super.paint(g); // 5 g.translate(-1, 0); super.paint(g); // 6 g.translate(-1, 0); super.paint(g); // 7 g.translate( 0, -1); super.paint(g); // 8 g.translate( 1, 0); // 9 isPaintingOutline = false; super.paint(g); forceTransparent = false; } public static void main(String[] args) { JFrame w = new JFrame(); w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); OutlineLabel label = new OutlineLabel("Test", OutlineLabel.CENTER); label.setOpaque(true); w.setContentPane(new JPanel(new BorderLayout())); w.add(label, BorderLayout.CENTER); w.pack(); w.setVisible(true); } }