【问题标题】:add subscripts and a font to a String in graphics on a JFrame在 JFrame 上的图形中为字符串添加下标和字体
【发布时间】:2017-11-29 14:22:27
【问题描述】:

我想在我的 JFrame 上绘制一个包含下标和字体的字符串,我试图使用 AttributedString 但我似乎不想工作,无论出于何种原因。它要么只显示字体,要么只显示下标,但不会同时显示两者。

private class DrawFormulas extends JComponent
{
    public void paint(Graphics g)
    {

        Graphics2D G2D = (Graphics2D)g;

        G2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g.setFont(F);

        AttributedString Trig = new AttributedString("a2 + b2 = c2");
        Trig.addAttribute(TextAttribute.FONT, F);
        Trig.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, 1, 2);
        Trig.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, 6, 7);
        Trig.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, 11, 12);
        Trig.addAttribute(TextAttribute.SIZE, F.getSize());
        G2D.drawString(Trig.getIterator(), 170, 75);

    }
}

如果有人能告诉我为什么这不起作用或有更好的方法来做到这一点,任何帮助将不胜感激。谢谢

【问题讨论】:

  • 你的字体是什么?
  • 它是 F,它是在方法 Font F = new Font("SANS_SERIF", Font.PLAIN, 60); 之外定义的;
  • 1+ 以获得不错的 sn-p,但是请确保下次您发布有效的 minimal reproducible example 时,我们不需要询问字体(或代码中的任何数据)是什么.我的回答显示了该 MCVE 的一个示例

标签: java swing graphics fonts subscript


【解决方案1】:

如果有人能告诉我为什么这不起作用

我不确定为什么同时使用 TextAttribute.FONT 和 TextAttribute.SUPERSCRIPT 不会合并这些属性

这是因为 FONT TextAttribute 以特殊方式处理。来自 javadoc:

... 通常,所有属性都被检查并用于选择和 配置一个字体实例。但是,如果存在 FONT 属性,它的 将使用关联的字体。 ... 通常,地图中除了 FONT 属性外没有其他属性。

Javadoc 还解释了其他属性可以与 FONT 属性一起使用,但不能与以下属性一起使用:FAMILY、WEIGHT、WIDTH、POSTURE、SIZE、TRANSFORM、SUPERSCRIPT 和 TRACKING。

这就是忽略 SUPERSCRIPT 属性的原因。

【讨论】:

    【解决方案2】:

    我不确定为什么同时使用 TextAttribute.FONTTextAttribute.SUPERSCRIPT 时不会合并这些属性,但 @thrashgod 的 answer 给出了您的解决方案的想法。

    Font对象分离成:

    • 字体大小 = 60
    • 字体系列 = Font.SANS_SERIF
    • 字体样式=Font.PLAIN

    由于样式很简单,我们只需要字体大小和字体系列,所以我以这样的方式结束:

    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.font.TextAttribute;
    import java.text.AttributedString;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class FormulaDrawer {
        private JFrame frame;
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new FormulaDrawer()::createAndShowGui);
        }
    
        private void createAndShowGui() {
            frame = new JFrame(getClass().getSimpleName());
    
            Drawer drawer = new Drawer();
    
            frame.add(drawer);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
        }
    
        @SuppressWarnings("serial")
        class Drawer extends JPanel {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    
                AttributedString trig = new AttributedString("a2 + b2 = c2");
                trig.addAttribute(TextAttribute.FAMILY, "Comic Sans MS"); //Change to Font.SANS_SERIF constant
                trig.addAttribute(TextAttribute.SIZE, 20);
    
                trig.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, 1, 2);
                trig.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, 6, 7);
                trig.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, 11, 12);
    
                g2d.drawString(trig.getIterator(), 50, 50);
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
        }
    }
    

    但是你可能已经注意到我使用了 20 而不是 60 的字体大小,那是因为它对我来说似乎太大了,只需更改它就可以了,而且我使用了另一种字体,所以你可以看到你可以使用您想要的任何字体(只需确保已安装该字体或将其导出到您的 JAR 文件中)

    一般的想法是单独使用字体属性,如上面代码中的这些行:

    trig.addAttribute(TextAttribute.FAMILY, "Comic Sans MS");
    trig.addAttribute(TextAttribute.SIZE, 20);
    

    这就是它的样子:)


    请务必关注Java naming conventions,以便您和我们更容易阅读您的代码:

    • firstWordLowerCaseVariable
    • firstWordLowerCaseMethod(...)
    • FirstWordUpperCaseClass
    • ALL_WORDS_UPPER_CASE_CONSTANT

    对您的代码的另一个改进是:尽量不要分别扩展和覆盖 JComponentpaint() 方法,而是扩展 JPanel 或任何其他组件并覆盖它的 paintComponent(Graphics g) 方法并确保调用 super.paintComponent(g) 为它里面的第一行,这样你就不会破坏油漆链。

    我的 main(...) 方法对您来说可能也很奇怪,因为 Java 8 中的 Method Reference 和您应该始终启动 Swing 程序的 Event Dispatch Thread (EDT)


    有没有办法用字体的样式来做到这一点?

    是的,有(如 thrashgod 答案的链接所示)

    您可以阅读TextAttribute 文档找到更多样式

    例如:

    trig.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
    trig.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    

    【讨论】:

    • 非常感谢,效果很好。你还有一个问题。我可以通过 F.getSize() 设置大小,也可以通过 F.getFamily() 设置族,但是有没有办法用字体样式来做到这一点?我很确定你用 TextAttribute.WEIGHT 设置它,但我不知道如何将它从字体中拉出来。
    • 感谢您的帮助,非常有帮助:)
    • 很高兴它有帮助,不要忘记考虑给出的提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-02
    相关资源
    最近更新 更多