javaswingtextjlabeltext-shadow

JLabel text shadow


I have a JLabel with text. The text displays in different colors and since I also want the background to change color, I found sometimes the text it's hard to read. That is why I want to add a shadow to the font like this: React Native font outline / textShadow

Can someone tell me how to get this effect in a Java Swing label or, if not possible, which Swing component I should use instead?


Solution

  • You can convert the text to an outline and stroke it.

    import javax.swing.*;
    import java.awt.*;
    import java.awt.font.FontRenderContext;
    import java.awt.font.TextLayout;
    import java.awt.image.BufferedImage;
    
    class Test extends JFrame {
        public Test() throws HeadlessException {
            setSize(500, 500);
            add(new JOutlineLabel("test"));
        }
        
        class JOutlineLabel extends JComponent {
            
            int width = 3;
            Shape outline;
            
            public JOutlineLabel(String string) {
                BufferedImage temp = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR);
                Graphics2D g2 = temp.createGraphics();
                
                FontRenderContext frc = g2.getFontRenderContext();
                Font font = new Font("Helvetica", 1, 60);
                
                TextLayout textLayout = new TextLayout(string, font, frc);
                outline = textLayout.getOutline(null);
            }
            
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                g2.translate(0, outline.getBounds().height);
                g2.setColor(Color.blue);
                g2.setStroke(new BasicStroke(width));
                g2.draw(outline);
            }
        }
        
        public static void main(String[] args) {
            new Test().setVisible(true);
        }
    }
    

    enter image description here

    You'll want to avoid the executing heavyweight bits like instantiating the Font, converting the text to an outline, etc every draw.