java 如何在 AWT 中围绕文本绘制轮廓?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10016001/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 23:16:06  来源:igfitidea点击:

How to draw an outline around text in AWT?

javaawt

提问by Konrad Garus

How can I draw an outline around any text in AWT, something similar to this picture?

如何在 AWT 中围绕任何文本绘制轮廓,类似于此图片?

Outline

大纲

采纳答案by mKorbel

two examples

两个例子

output from this paint would be the BufferedImage, for AWT Components use method paint(), for Swing JComponents is there paintComponet()

此绘制的输出将是BufferedImage,对于 AWT 组件使用方法paint(),对于 Swing JComponents 是存在的paintComponet()

Also, from code linked in a comment:

此外,来自注释中链接的代码:

回答by Eddo

Try the following:

请尝试以下操作:

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);
    }
}

回答by CodeBlind

Not sure how you're drawing the text now, but one way you could do it is use a BufferedImage as an overlay to whatever it is that you're drawing on.

不确定您现在是如何绘制文本的,但是您可以使用的一种方法是使用 BufferedImage 作为您正在绘制的任何内容的叠加。

  1. Create BufferedImage using the dimensions of the string and font you are wanting to draw with (look at FontMetrics class for this).
  2. Fill the BufferedImage with transparency.
  3. Draw your string onto the BufferedImage with whatever color you want.
  4. Iterate over every pixel in the BufferedImage and see how far away it is from a pixel of your text's color. If it's within a certain distance, draw that pixel black, and maybe more transparent if it's further away from the color of your text. Of course, if the pixel is already the same color as your text color, then ignore it.
  5. Draw BufferedImage onto whatever it is that you're painting onto.
  1. 使用要绘制的字符串和字体的尺寸创建 BufferedImage(查看 FontMetrics 类)。
  2. 用透明度填充 BufferedImage。
  3. 使用您想要的任何颜色将您的字符串绘制到 BufferedImage 上。
  4. 迭代 BufferedImage 中的每个像素,看看它与文本颜色的像素有多远。如果它在一定距离内,将该像素绘制为黑色,如果它离文本颜色更远,则可能会更透明。当然,如果像素已经与您的文本颜色相同,则忽略它。
  5. 将 BufferedImage 绘制到您要绘制的任何对象上。

EDIT

编辑

There may be libraries out there that already do this, but if I had to code it from scratch, this is how I'd try to do it.

可能有一些库已经这样做了,但是如果我必须从头开始编写代码,这就是我尝试这样做的方式。

回答by Booyah Johnson

Here is a hacky example. It is not as sophisticated as others, but it is simpler to understand, and it behaves like a JLabel.

这是一个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);
    }
}

回答by guness

some stupidest workarounds: -type same words twice but one of them is black and the other is white, put white on top of the black one, you may get something similar. -find a font looks like above the example, and use it.

一些最愚蠢的解决方法: - 输入相同的单词两次,但其中一个是黑色的,另一个是白色的,将白色放在黑色的上面,你可能会得到类似的东西。- 找到一个看起来像上面例子的字体,并使用它。