How to output a String on multiple lines using Graphics

后端 未结 5 1895
清酒与你
清酒与你 2020-12-28 09:39

My Program overrides public void paint(Graphics g, int x, int y); in order to draw some stings using g.drawString(someString, x+10, y+30);

相关标签:
5条回答
  • 2020-12-28 10:01

    Had some trouble myself this is my solution:

    Graphics2D g=....
    FontRenderContext frc = g.getFontRenderContext();
    TextLayout layout = new TextLayout(text, font, frc);
    String[] outputs = text.split("\n");
    for(int i=0; i<outputs.length; i++){
        g.drawString(outputs[i], 15,(int) (15+i*layout.getBounds().getHeight()+0.5));
    

    Hope that helps.... simple but it works.

    0 讨论(0)
  • 2020-12-28 10:04

    java.awt.font.TextLayout might be helpful. Here's a snippet of their example code:

       Graphics2D g = ...;
       Point2D loc = ...;
       Font font = Font.getFont("Helvetica-bold-italic");
       FontRenderContext frc = g.getFontRenderContext();
       TextLayout layout = new TextLayout("This is a string", font, frc);
       layout.draw(g, (float)loc.getX(), (float)loc.getY());
    
       Rectangle2D bounds = layout.getBounds();
       bounds.setRect(bounds.getX()+loc.getX(),
                      bounds.getY()+loc.getY(),
                      bounds.getWidth(),
                      bounds.getHeight());
       g.draw(bounds);
    

    Otherwise you could always use a Swing text element to do the job for you, just pass in the Graphics you want it to paint into.

    0 讨论(0)
  • 2020-12-28 10:07

    Thanks to Epaga's hint and a couple of examples on the Net (not so obvious to find! I used mainly Break a Line for text layout), I could make a component to display wrapped text. It is incomplete, but at least it shows the intended effect.

    class TextContainer extends JPanel
    {
        private int m_width;
        private int m_height;
        private String m_text;
        private AttributedCharacterIterator m_iterator;
        private int m_start;
        private int m_end;
    
        public TextContainer(String text, int width, int height)
        {
            m_text = text;
            m_width = width;
            m_height = height;
    
            AttributedString styledText = new AttributedString(text);
            m_iterator = styledText.getIterator();
            m_start = m_iterator.getBeginIndex();
            m_end = m_iterator.getEndIndex();
        }
    
        public String getText()
        {
            return m_text;
        }
    
        public Dimension getPreferredSize()
        {
            return new Dimension(m_width, m_height);
        }
    
        public void paint(Graphics g)
        {
            super.paintComponent(g);
    
            Graphics2D g2 = (Graphics2D) g;
            FontRenderContext frc = g2.getFontRenderContext();
    
            LineBreakMeasurer measurer = new LineBreakMeasurer(m_iterator, frc);
            measurer.setPosition(m_start);
    
            float x = 0, y = 0;
            while (measurer.getPosition() < m_end)
            {
                TextLayout layout = measurer.nextLayout(m_width);
    
                y += layout.getAscent();
                float dx = layout.isLeftToRight() ?
                        0 : m_width - layout.getAdvance();
    
                layout.draw(g2, x + dx, y);
                y += layout.getDescent() + layout.getLeading();
            }
        }
    }
    

    Just for fun, I made it fitting a circle (alas, no justification, it seems):

    public void paint(Graphics g)
    {
        super.paintComponent(g);
    
        Graphics2D g2 = (Graphics2D) g;
        FontRenderContext frc = g2.getFontRenderContext();
    
        LineBreakMeasurer measurer = new LineBreakMeasurer(m_iterator, frc);
        measurer.setPosition(m_start);
    
        float y = 0;
        while (measurer.getPosition() < m_end)
        {
            double ix = Math.sqrt((m_width / 2 - y) * y);
            float x = m_width / 2.0F - (float) ix;
            int width = (int) ix * 2;
    
            TextLayout layout = measurer.nextLayout(width);
    
            y += layout.getAscent();
            float dx = layout.isLeftToRight() ?
                    0 : width - layout.getAdvance();
    
            layout.draw(g2, x + dx, y);
            y += layout.getDescent() + layout.getLeading();
        }
    }
    

    I am not too sure about dx computation, though.

    0 讨论(0)
  • 2020-12-28 10:11

    Incrementally build your string, one word at a time, using Epaga's method to find the length of your string. Once the length is longer than your rectangle, remove the last word and print. Repeat until you run out of words.

    It sounds like a bad algorithm, but for each line, it's really O(screenWidth/averageCharacterWidth) => O(1).

    Still, use a StringBuffer to build your string!

    0 讨论(0)
  • 2020-12-28 10:23

    You can use a JLabel and embed the text with html.

    JLabel.setText("<html>"+line1+"<br>"+line2);
    
    0 讨论(0)
提交回复
热议问题