Java图形随机文本 [英] Java graphics random text

查看:54
本文介绍了Java图形随机文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用drawString(word, x, y)和x,y值随机,根据BufferedImage上的单词频率使用fontSize绘制随机文本.不幸的是,它绘制了重叠的随机文本.图像帧大小为1200 x 650,x,y的随机数在这些值之间.这是我的代码:

I'm trying to draw random text with fontSize based on word frequency on the BufferedImage using the drawString(word, x, y) with random x,y values. Unfortunately it draws the random text that is overlaping. The image frame size is 1200 x 650 and the random numbers for x, y are between these values. Here's my code:

Random rand = new Random();
Font f = getRandomFont(fontSize);
FontMetrics metrics = graphics.getFontMetrics(f);
AffineTransform affinetransform = new AffineTransform();     
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
int textwidth = (int)(f.getStringBounds(word, frc).getWidth());
int textheight = (int)(f.getStringBounds(word, frc).getHeight());
graphics.setColor(Color.red);
graphics.setFont(f);
int x = textwidth + rand.nextInt(800);
int y = -textheight + rand.nextInt(800);
graphics.drawString(word, x , y );

推荐答案

首先,在基线"周围绘制字体,即y位置代表基线,因此文本可以在其上方和下方生长.它...

First, fonts are drawn around the "base line", that is, the y position represents the baseline, so the text can grow above it and below it...

因此,您应该使用FontMetrics#getAscent

第二,您需要跟踪所有先前绘制过的文本位置,可以使用FontMetrics#getStringBounds来实现,它返回一个Rectangle2D并保留一个列表,您可以对其进行迭代检查如果新文本与其他任何文本相交,例如...

Second, you need to keep track of all the previous locations text was painted, you could do this by using FontMetrics#getStringBounds, which returns a Rectangle2D and simply keep a list of this, which you can iterate over to check if the new text intersects any other, as an example...

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.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img;

        public TestPane() {
            img = new BufferedImage(1200, 650, BufferedImage.TYPE_INT_ARGB);
            try (BufferedReader br = new BufferedReader(new FileReader(new File("Words.txt")))) {
                List<String> words = new ArrayList<>(25);
                String text = null;
                System.out.println("Read");
                while ((text = br.readLine()) != null) {
                    words.add(text);
                }
                System.out.println("Loaded " + words.size());

                Collections.sort(words);

                Random rnd = new Random();
                Font font = getFont();
                Graphics2D g2d = img.createGraphics();
                g2d.setColor(Color.WHITE);
                g2d.fillRect(0, 0, 1200, 650);

                List<Rectangle2D> used = new ArrayList<>(25);
                for (String word : words) {
                    int size = rnd.nextInt(37) + 11;
                    Font drawFont = font.deriveFont((float) size);
                    FontMetrics fm = g2d.getFontMetrics(drawFont);
                    Rectangle2D bounds = fm.getStringBounds(word, g2d);
                    System.out.println("Positing " + word);
                    do {
                        int xPos = rnd.nextInt(1200 - (int)bounds.getWidth());
                        int yPos = rnd.nextInt(650 - (int)bounds.getHeight());

                        bounds.setFrame(xPos, yPos, bounds.getWidth(), bounds.getHeight());
                    } while (collision(used, bounds));
                    used.add(bounds);
                    g2d.setFont(drawFont);
                    g2d.setColor(Color.BLACK);
                    g2d.drawString(word, (float)bounds.getX(), (float)bounds.getY() + fm.getAscent());
                    g2d.setColor(Color.RED);
                    g2d.draw(bounds);
                }
                g2d.dispose();
            } catch (IOException exp) {
                exp.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(1200, 650);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(img, 0, 0, this);
            g2d.dispose();
        }

        protected boolean collision(List<Rectangle2D> used, Rectangle2D bounds) {
            boolean collides = false;
            for (Rectangle2D check : used) {
                if (bounds.intersects(check)) {
                    collides = true;
                    break;
                }
            }
            return collides;
        }

    }

}

红色矩形仅用于演示目的,您可以摆脱它们.

The red rectangles are just for demonstration purposes and you can get rid of those.

但是,这确实表现出一个小问题,并非所有文本都填充了所有矩形.

This does, however, demonstrate a small problem, not all the text fills all of the rectangle.

更复杂的解决方案是使用TextLayout生成文本的Shape,这将使单词分组在一起非常紧密.

A more complex solution would be to use a TextLayout to generate a Shape of the text, which would allow words to be grouped much closed together.

看看将图像分配给字符串演示如何生成

这篇关于Java图形随机文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆