为啥 Graphics2D.setStoke() 不适用于 Graphics2D.drawString?

Posted

技术标签:

【中文标题】为啥 Graphics2D.setStoke() 不适用于 Graphics2D.drawString?【英文标题】:Why doesn't Graphics2D.setStoke() work for Graphics2D.drawString?为什么 Graphics2D.setStoke() 不适用于 Graphics2D.drawString? 【发布时间】:2014-09-14 06:07:18 【问题描述】:

我希望字符串具有不同的宽度,以便设置 Graphics2D 的笔画,代码在这里:

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

但是,当我使用 g2d.setStroke(new BasicStroke(10)); 时它不起作用 提前感谢您的帮助。

【问题讨论】:

因为drawString没有能够Stroke的概念 对于一些想法,check out this @MadProgrammer。谢谢,我将使用字体来实现我的目标。 【参考方案1】:

基本上,字体/文本的渲染过程与其他图形元素不同,因此它们通常不受笔画等因素的影响。

为了渲染带有笔划的文本,需要先将其转换为Shape,例如...

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


【讨论】:

这其实是图形有趣的一面,希望对您有所帮助

以上是关于为啥 Graphics2D.setStoke() 不适用于 Graphics2D.drawString?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 glTranslatef?为啥不直接更改渲染坐标?

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?