0

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?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
GalliadII
  • 162
  • 1
  • 14
  • 5
    Maybe this helps: https://stackoverflow.com/q/65719460/9721857 – Lucadmin Jul 20 '21 at 22:24
  • sadly no. The author works in a completly different way than I do. I cannot even follow what they are trying to achieve let alone what their code even does. – GalliadII Jul 21 '21 at 00:02
  • @galliadll If you’re going to work with a JLabel, then the linked solution would almost be a drop in replacement. Any other solution is going to be vastly more complicated – MadProgrammer Jul 21 '21 at 03:52
  • sorry to say this, but the author basically writes a code that does only this one task inside the class. But I find the way they use inheritance counterproductive as soon as the program gets bigger. I have bigger code where this is only a portion of what it should achieve. I do not want to restructure my entire class and have days of rework just for one simple effect. – GalliadII Jul 22 '21 at 23:23

1 Answers1

2

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.

Charlie
  • 8,530
  • 2
  • 55
  • 53
  • thank you for the answer, but I do barely understand this code. I would basically have to just copy it for my project. I am not sure how to do that and to "avoid the executing heavyweight" since I cannot even filter that out. Would you be so kind to delete the lines you mean I should leave out? – GalliadII Jul 21 '21 at 09:27
  • thank you very much. I almost got it. I just need 2 more clarifications: 1. in the line: g2.translate(0, outline.getBounds().height); I find the getBounds() method not to be resolvable. 2. My code can also not handle the width 2 lines below. Proably as a direct result. I am not using any layout managers. Layout is null and I use setBounds for everything to place everything where I want it. But setBounds does not get resolved on either the shape nor the Graphics2D. – GalliadII Jul 23 '21 at 15:35
  • What java runtime and version are you using? The translate is moving the text draw down by the height of the text because otherwise it draws above the window/component as the text is at negative Y coordinates. – Charlie Jul 23 '21 at 18:31
  • Shape.getBounds() has been around since Java 1.2 so I'm not sure what's going on there. https://docs.oracle.com/javase/7/docs/api/java/awt/Shape.html#getBounds() – Charlie Jul 23 '21 at 18:33