Java 在JFrame的图形中向字符串添加下标和字体

Java 在JFrame的图形中向字符串添加下标和字体,java,swing,graphics,fonts,subscript,Java,Swing,Graphics,Fonts,Subscript,我想在我的JFrame上画一个有下标和字体的字符串,我试图使用AttributedString,但我似乎不想因为任何原因工作。它要么只显示字体,要么只显示下标,但不能同时显示两者 private class DrawFormulas extends JComponent { public void paint(Graphics g) { Graphics2D G2D = (Graphics2D)g; G2D.setRenderingHint(R

我想在我的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);

    }
}

如果有人能告诉我为什么这不起作用,或者有更好的方法来做这件事,我们将不胜感激。谢谢

我不知道为什么同时使用
texttribute.FONT
texttribute.SUPERSCRIPT
不会合并这些属性,但是@thrashgod的这篇文章给出了您的解决方案

字体
对象分为:

  • 字体大小=60
  • 字体系列=
    Font.SANS\u 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);
这就是它的样子:)


另外,请务必遵循以下步骤,以便您和我们更容易阅读您的代码:

  • firstWordLowerCaseVariable
  • firstWordLowerCaseMethod(…)
  • FirstWordUpperCaseClass
  • 所有单词大写常量
代码的另一个改进是:尝试不分别扩展和重写
JComponent
paint()
方法,而是扩展
JPanel
或任何其他组件并重写它的
paintComponent(Graphics g)
方法,并确保调用
super.paintComponent(g)
作为其中的第一行,这样您就不会破坏油漆链

我的
main(…)
方法对您来说可能也很奇怪,因为在Java8中有一个


有没有一种方法可以用字体的样式来实现这一点

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

  • 粗体文本带有
  • 斜体文本带有
阅读文档可以找到更多样式

例如:

trig.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
trig.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
如果有人能告诉我为什么这不起作用


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

这是因为FONT TextAttribute是以一种特殊的方式处理的。从javadoc:

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

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


这就是上标属性被忽略的原因。

哪种字体是您的字体?它是在方法font F=新字体(“SANS_SERIF”,font.PLAIN,60)之外定义的F;1+对于一个好的代码段,但是请确保下次发布有效的代码时,我们不需要询问字体(或代码中的任何数据)是什么。我的回答显示了一个例子,麦克维特非常感谢你,它非常有效。你还有一个问题。我可以通过F.getSize()设置大小,也可以通过F.getFamily()设置族,但是有没有一种方法可以通过字体的样式来实现呢?我很确定您是用TextAttribute.WEIGHT设置的,但我不知道如何将其从字体中删除。谢谢您的帮助,它非常有用:)很高兴它有帮助,别忘了考虑给出的提示。