Search code examples
javaswingfontsawtstroke

Why doesn't Graphics2D.setStoke() work for Graphics2D.drawString?


I want the string to have different width so that I set the stroke of Graphics2D and the code is here:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class StrokeTest {
    public static void main(String[] args) {
        StrokeTest test = new StrokeTest();
        test.createUI();
    }

    public void createUI(){
        JFrame frame = new JFrame();
        frame.add(new MainPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    @SuppressWarnings("serial")
    class MainPanel extends JPanel{
        public MainPanel(){
            setPreferredSize(new Dimension(400, 300));
        }
        protected void paintComponent(Graphics g){
            Graphics2D g2d = (Graphics2D)g;
            g2d.setColor(Color.red);
            g2d.setStroke(new BasicStroke(10));
            g2d.drawString("I am a string", 100, 100);
        }
    }
}

However, it doesn't work when I use g2d.setStroke(new BasicStroke(10)); Thanks in advance for your help.


Solution

  • Basically, fonts/text are rendered using a different process then other graphics elements, so they are generally unaffected by such things as stroke.

    In order to render text with a stroke, you need to convert it to a Shape first, for example...

    Stroked

    import java.awt.BasicStroke;
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.Shape;
    import java.awt.font.FontRenderContext;
    import java.awt.font.TextLayout;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class TextStroke {
    
        public static void main(String[] args) {
            new TextStroke();
        }
    
        public TextStroke() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            public TestPane() {
                Font font = getFont();
                setFont(font.deriveFont(Font.PLAIN, 80));
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(800, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                int width = getWidth();
                int height = getHeight();
    
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
    
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
                        RenderingHints.VALUE_RENDER_QUALITY);
    
                FontRenderContext frc = g2d.getFontRenderContext();
                String s = "Look ma, I'm Stroked";
                TextLayout textTl = new TextLayout(s, getFont(), frc);
                Shape outline = textTl.getOutline(null);
    
                FontMetrics fm = g2d.getFontMetrics(getFont());
                int x = (getWidth() - outline.getBounds().width) / 2;
                int y = ((getHeight() - outline.getBounds().height) / 2) + fm.getAscent();
                g2d.translate(x, y);
    
    //            Stroke stroke = g2d.getStroke();
                g2d.setColor(Color.BLACK);
                g2d.fill(outline);
                g2d.setStroke(new BasicStroke(5));
                g2d.setColor(Color.RED);
                g2d.draw(outline);
                g2d.dispose();
            }
        }
    
    }