【问题标题】:Java: Graphics aligning StringsJava:图形对齐字符串
【发布时间】:2014-05-20 00:42:29
【问题描述】:

我目前正在尝试创建一个滚动文本方法,其中将采用String 的参数。很快,它将开始从左到右绘制,并随着时间的推移进入新的行,因此它不会从屏幕上绘制出来。我正在使用FontMetrics 来尝试实现我的目标。

我从我的主类中的渲染方法将参数传递给我的RollingText.render(Graphics g, int x, int y)。在我的render 方法中,我开始设置Graphics 字体和颜色,并抓取所有FontMetrics,然后我开始从FontMetrics 抓取不同的东西。同样,我进入了一个用于将文本绘制到字符串的 for 循环。

public void render(Graphics g, int x, int y) {
    // text is the field that a grab the index of the string from
    // the index is the max part of the string I'm grabbing from,
    // increments using the update() method
    String str = text.substring(0, index);
    String[] words = str.split(" ");

    Font f = new Font(g.getFont().getName(), 0, 24);
    FontMetrics fmetrics = g.getFontMetrics(f);
    g.setColor(Color.white);
    g.setFont(f);

    int line = 1;
    int charsDrawn = 0;
    int wordsDrawn = 0;
    int charWidth = fmetrics.charWidth('a');
    int fontHeight = fmetrics.getHeight();
    for (int i = 0; i < words.length; i++) {
        int wordWidth = fmetrics.stringWidth(words[i]);
        if (wordWidth* wordsDrawn + charWidth * charsDrawn > game.getWidth()) {
            line++;
            charsDrawn = 0;
            wordsDrawn = 0;
        }

        g.drawString(words[i], x * charsDrawn + charWidth, y + fontHeight * line);

        charsDrawn += words[i].length();
        wordsDrawn += 1;
    }
}

目前,此时一切正常,但留下的问题是drawString 方法中每个单词之间的空格被严重夸大了,如下所示:

行:

g.drawString(words[i], x * charsDrawn + charWidth, y + fontHeight * line);

我目前遇到的唯一问题是找到正确的方法来计算 x 位置。目前,它的间距很大且动态取决于字长,我无法弄清楚如何让它看起来至少正常。我用我当前定义的整数尝试了不同的组合,等等。出现的问题包括不正确的间距、过度的定位和闪烁,以及一起运行的文本。

最后,我的问题是,什么样的算法可以帮助我正确定位 x 坐标以使文本看起来正确?

【问题讨论】:

    标签: java fonts graphics2d fontmetrics java-canvas


    【解决方案1】:

    我不确定您为什么要尝试根据各种不同的变量计算 x/y 位置,而在我的介意...

    您似乎也在使用FontMetrics#stringWidth 和根据“样本”宽度计算单个字符的宽度...wordsDrawn + charWidth 之间切换,这使您的计算变得简单...令人困惑。您似乎也有优先级问题...

    x * charsDrawn + charWidth 不应该是x + (charsDrawn * charWidth)吗?

    我实际上无法获得您的示例代码来重现您的结果,相反,我对其进行了简化...

    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 javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class RenderText {
    
        public static void main(String[] args) {
            new RenderText();
        }
    
        public RenderText() {
            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 {
    
            private String text;
            private int index;
    
            public TestPane() {
                text = "A long time ago, in a galaxy far, far, away..."
                        + "A vast sea of stars serves as the backdrop for the main title. "
                        + "War drums echo through the heavens as a rollup slowly crawls "
                        + "into infinity."
                        + "     It is a period of civil war. Rebel spaceships, "
                        + "     striking from a hidden base, have won their first "
                        + "     victory against the evil Galactic Empire."
                        + "     During the battle, Rebel spies managed to steal "
                        + "     secret plans to the Empire's ultimate weapon, the "
                        + "     Death Star, an armored space station with enough "
                        + "     power to destroy an entire planet."
                        + "     Pursued by the Empire's sinister agents, Princess "
                        + "     Leia races home aboard her starship, custodian of "
                        + "     the stolen plans that can save her people and "
                        + "     restore freedom to the galaxy...";
    
                index = text.length() - 1;
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                render(g, 0, 0);
                g2d.dispose();
            }
    
            public void render(Graphics g, int x, int y) {
                // text is the field that a grab the index of the string from
                // the index is the max part of the string I'm grabbing from,
                // increments using the update() method
                String str = text.substring(0, index);
                String[] words = str.split(" ");
    
                Font f = new Font(g.getFont().getName(), 0, 24);
                FontMetrics fmetrics = g.getFontMetrics(f);
    //            g.setColor(Color.white);
                g.setFont(f);
    
                int fontHeight = fmetrics.getHeight();
    
                int spaceWidth = fmetrics.stringWidth(" ");
    
                int xPos = x;
                int yPos = y;
                for (String word : words) {
                    int wordWidth = fmetrics.stringWidth(word);
                    if (wordWidth + xPos > getWidth()) {
                        yPos += fontHeight;
                        xPos = x;
                    }
                    g.drawString(word, x + xPos, yPos + fmetrics.getAscent());
                    xPos += wordWidth + spaceWidth;
                }
            }
        }
    
    }
    

    在你能提供一个实际的runnable example that demonstrates your problem 之前,这是我能做的最好的......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多